aboutsummaryrefslogtreecommitdiff
path: root/ubifs-utils
diff options
context:
space:
mode:
authorZhihao Cheng <chengzhihao1@huawei.com>2024-11-11 16:36:45 +0800
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2024-11-11 10:32:45 +0100
commitb4460065025ef82f47cf4afa36f6db3b22bda591 (patch)
tree4616775a3b7975ed9252f680ef33e129efc9881c /ubifs-utils
parent146888d3da3cd1ba39b7805a7686fde6adf7549a (diff)
ubifs-utils: Add atomic implementations
Add atomic implementations, because there are some atomic operations (eg. atomic_long_xxx) used in UBIFS linux kernel libs. This is a preparation for replacing implementation of UBIFS utils with linux kernel libs. Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com> Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'ubifs-utils')
-rw-r--r--ubifs-utils/Makemodule.am1
-rw-r--r--ubifs-utils/common/atomic.h133
2 files changed, 134 insertions, 0 deletions
diff --git a/ubifs-utils/Makemodule.am b/ubifs-utils/Makemodule.am
index 13171b7..5816257 100644
--- a/ubifs-utils/Makemodule.am
+++ b/ubifs-utils/Makemodule.am
@@ -2,6 +2,7 @@ common_SOURCES = \
ubifs-utils/common/compiler_attributes.h \
ubifs-utils/common/linux_types.h \
ubifs-utils/common/linux_err.h \
+ ubifs-utils/common/atomic.h \
ubifs-utils/common/kmem.h \
ubifs-utils/common/kmem.c \
ubifs-utils/common/defs.h \
diff --git a/ubifs-utils/common/atomic.h b/ubifs-utils/common/atomic.h
new file mode 100644
index 0000000..f287d43
--- /dev/null
+++ b/ubifs-utils/common/atomic.h
@@ -0,0 +1,133 @@
+//Source: http://golubenco.org/atomic-operations.html
+#ifndef __ATOMIC_H__
+#define __ATOMIC_H__
+
+/* Check GCC version, just to be safe */
+#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
+# error atomic.h works only with GCC newer than version 4.1
+#endif /* GNUC >= 4.1 */
+
+/**
+ * Atomic type.
+ */
+typedef struct {
+ volatile long counter;
+} atomic_long_t;
+
+#define ATOMIC_INIT(i) { (i) }
+
+/**
+ * Read atomic variable
+ * @param v pointer of type atomic_long_t
+ *
+ * Atomically reads the value of @v.
+ */
+#define atomic_long_read(v) ((v)->counter)
+
+/**
+ * Set atomic variable
+ * @param v pointer of type atomic_long_t
+ * @param i required value
+ */
+#define atomic_long_set(v,i) (((v)->counter) = (i))
+
+/**
+ * Add to the atomic variable
+ * @param i integer value to add
+ * @param v pointer of type atomic_long_t
+ */
+static inline void atomic_long_add( int i, atomic_long_t *v )
+{
+ (void)__sync_add_and_fetch(&v->counter, i);
+}
+
+/**
+ * Subtract the atomic variable
+ * @param i integer value to subtract
+ * @param v pointer of type atomic_long_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+static inline void atomic_long_sub( int i, atomic_long_t *v )
+{
+ (void)__sync_sub_and_fetch(&v->counter, i);
+}
+
+/**
+ * Subtract value from variable and test result
+ * @param i integer value to subtract
+ * @param v pointer of type atomic_long_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+static inline int atomic_long_sub_and_test( int i, atomic_long_t *v )
+{
+ return !(__sync_sub_and_fetch(&v->counter, i));
+}
+
+/**
+ * Increment atomic variable
+ * @param v pointer of type atomic_long_t
+ *
+ * Atomically increments @v by 1.
+ */
+static inline void atomic_long_inc( atomic_long_t *v )
+{
+ (void)__sync_fetch_and_add(&v->counter, 1);
+}
+
+/**
+ * @brief decrement atomic variable
+ * @param v: pointer of type atomic_long_t
+ *
+ * Atomically decrements @v by 1. Note that the guaranteed
+ * useful range of an atomic_long_t is only 24 bits.
+ */
+static inline void atomic_long_dec( atomic_long_t *v )
+{
+ (void)__sync_fetch_and_sub(&v->counter, 1);
+}
+
+/**
+ * @brief Decrement and test
+ * @param v pointer of type atomic_long_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+static inline int atomic_long_dec_and_test( atomic_long_t *v )
+{
+ return !(__sync_sub_and_fetch(&v->counter, 1));
+}
+
+/**
+ * @brief Increment and test
+ * @param v pointer of type atomic_long_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+static inline int atomic_long_inc_and_test( atomic_long_t *v )
+{
+ return !(__sync_add_and_fetch(&v->counter, 1));
+}
+
+/**
+ * @brief add and test if negative
+ * @param v pointer of type atomic_long_t
+ * @param i integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+static inline int atomic_long_add_negative( int i, atomic_long_t *v )
+{
+ return (__sync_add_and_fetch(&v->counter, i) < 0);
+}
+
+#endif