atomic.h 2.9 KB

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