diff options
author | Zhihao Cheng <chengzhihao1@huawei.com> | 2024-11-11 16:36:45 +0800 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2024-11-11 10:32:45 +0100 |
commit | b4460065025ef82f47cf4afa36f6db3b22bda591 (patch) | |
tree | 4616775a3b7975ed9252f680ef33e129efc9881c /ubifs-utils/common | |
parent | 146888d3da3cd1ba39b7805a7686fde6adf7549a (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/common')
-rw-r--r-- | ubifs-utils/common/atomic.h | 133 |
1 files changed, 133 insertions, 0 deletions
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 |