Line data Source code
1 : //Source: http://golubenco.org/atomic-operations.html
2 : #ifndef __ATOMIC_H__
3 : #define __ATOMIC_H__
4 :
5 : /* Check GCC version, just to be safe */
6 : #if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
7 : # error atomic.h works only with GCC newer than version 4.1
8 : #endif /* GNUC >= 4.1 */
9 :
10 : /**
11 : * Atomic type.
12 : */
13 : typedef struct {
14 : volatile long counter;
15 : } atomic_long_t;
16 :
17 : #define ATOMIC_INIT(i) { (i) }
18 :
19 : /**
20 : * Read atomic variable
21 : * @param v pointer of type atomic_long_t
22 : *
23 : * Atomically reads the value of @v.
24 : */
25 : #define atomic_long_read(v) ((v)->counter)
26 :
27 : /**
28 : * Set atomic variable
29 : * @param v pointer of type atomic_long_t
30 : * @param i required value
31 : */
32 : #define atomic_long_set(v,i) (((v)->counter) = (i))
33 :
34 : /**
35 : * Add to the atomic variable
36 : * @param i integer value to add
37 : * @param v pointer of type atomic_long_t
38 : */
39 : static inline void atomic_long_add( int i, atomic_long_t *v )
40 : {
41 : (void)__sync_add_and_fetch(&v->counter, i);
42 : }
43 :
44 : /**
45 : * Subtract the atomic variable
46 : * @param i integer value to subtract
47 : * @param v pointer of type atomic_long_t
48 : *
49 : * Atomically subtracts @i from @v.
50 : */
51 : static inline void atomic_long_sub( int i, atomic_long_t *v )
52 : {
53 1933 : (void)__sync_sub_and_fetch(&v->counter, i);
54 : }
55 :
56 : /**
57 : * Subtract value from variable and test result
58 : * @param i integer value to subtract
59 : * @param v pointer of type atomic_long_t
60 : *
61 : * Atomically subtracts @i from @v and returns
62 : * true if the result is zero, or false for all
63 : * other cases.
64 : */
65 : static inline int atomic_long_sub_and_test( int i, atomic_long_t *v )
66 : {
67 : return !(__sync_sub_and_fetch(&v->counter, i));
68 : }
69 :
70 : /**
71 : * Increment atomic variable
72 : * @param v pointer of type atomic_long_t
73 : *
74 : * Atomically increments @v by 1.
75 : */
76 : static inline void atomic_long_inc( atomic_long_t *v )
77 : {
78 1141489415 : (void)__sync_fetch_and_add(&v->counter, 1);
79 : }
80 :
81 : /**
82 : * @brief decrement atomic variable
83 : * @param v: pointer of type atomic_long_t
84 : *
85 : * Atomically decrements @v by 1. Note that the guaranteed
86 : * useful range of an atomic_long_t is only 24 bits.
87 : */
88 : static inline void atomic_long_dec( atomic_long_t *v )
89 : {
90 6837066 : (void)__sync_fetch_and_sub(&v->counter, 1);
91 : }
92 :
93 : /**
94 : * @brief Decrement and test
95 : * @param v pointer of type atomic_long_t
96 : *
97 : * Atomically decrements @v by 1 and
98 : * returns true if the result is 0, or false for all other
99 : * cases.
100 : */
101 : static inline int atomic_long_dec_and_test( atomic_long_t *v )
102 : {
103 : return !(__sync_sub_and_fetch(&v->counter, 1));
104 : }
105 :
106 : /**
107 : * @brief Increment and test
108 : * @param v pointer of type atomic_long_t
109 : *
110 : * Atomically increments @v by 1
111 : * and returns true if the result is zero, or false for all
112 : * other cases.
113 : */
114 : static inline int atomic_long_inc_and_test( atomic_long_t *v )
115 : {
116 : return !(__sync_add_and_fetch(&v->counter, 1));
117 : }
118 :
119 : /**
120 : * @brief add and test if negative
121 : * @param v pointer of type atomic_long_t
122 : * @param i integer value to add
123 : *
124 : * Atomically adds @i to @v and returns true
125 : * if the result is negative, or false when
126 : * result is greater than or equal to zero.
127 : */
128 : static inline int atomic_long_add_negative( int i, atomic_long_t *v )
129 : {
130 : return (__sync_add_and_fetch(&v->counter, i) < 0);
131 : }
132 :
133 : #endif
|