jatomic.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #ifndef JATOMIC_HPP
  15. #define JATOMIC_HPP
  16. #include "platform.h"
  17. #ifdef _WIN32
  18. extern "C"
  19. {
  20. LONG __cdecl _InterlockedIncrement(LONG volatile *Addend);
  21. LONG __cdecl _InterlockedDecrement(LONG volatile *Addend);
  22. LONG __cdecl _InterlockedCompareExchange(LONG volatile * Dest, LONG Exchange, LONG Comp);
  23. }
  24. #pragma intrinsic (_InterlockedCompareExchange)
  25. #define InterlockedCompareExchange _InterlockedCompareExchange
  26. #pragma intrinsic (_InterlockedIncrement)
  27. #define InterlockedIncrement _InterlockedIncrement
  28. #pragma intrinsic (_InterlockedDecrement)
  29. #define InterlockedDecrement _InterlockedDecrement
  30. typedef volatile long atomic_t;
  31. #define ATOMIC_INIT(i) (i)
  32. #define atomic_inc(v) InterlockedIncrement(v)
  33. #define atomic_inc_and_test(v) (InterlockedIncrement(v) == 0)
  34. #define atomic_dec(v) InterlockedDecrement(v)
  35. #define atomic_dec_and_test(v) (InterlockedDecrement(v) == 0)
  36. #define atomic_read(v) (*v)
  37. #define atomic_set(v,i) ((*v) = (i))
  38. #define atomic_xchg(i, v) InterlockedExchange(v, i)
  39. #define atomic_add(v,i) InterlockedAdd(v,i)
  40. #define atomic_add_exchange(v, i) InterlockedExchangeAdd(v,i)
  41. #define atomic_xchg_ptr(p, v) InterlockedExchangePointer(v,p)
  42. #if defined (_MSC_VER) && (_MSC_VER <= 1200)
  43. #define atomic_cas(v,newvalue,expectedvalue) (InterlockedCompareExchange((PVOID *)(v),(PVOID)(long)(newvalue),(PVOID)(long)(expectedvalue))==(PVOID)(long)(expectedvalue))
  44. #define atomic_cas_ptr(v, newvalue,expectedvalue) atomic_cas(v,(long)newvalue,(long)expectedvalue)
  45. #else
  46. #define atomic_cas(v,newvalue,expectedvalue) (InterlockedCompareExchange(v,newvalue,expectedvalue)==expectedvalue)
  47. #define atomic_cas_ptr(v, newvalue,expectedvalue) (InterlockedCompareExchangePointer(v,newvalue,expectedvalue)==expectedvalue)
  48. #endif
  49. #elif defined(__GNUC__)
  50. typedef struct { volatile int counter; } atomic_t;
  51. #define ATOMIC_INIT(i) { (i) }
  52. #define atomic_read(v) ((v)->counter)
  53. #define atomic_set(v,i) (((v)->counter) = (i))
  54. static __inline__ bool atomic_dec_and_test(atomic_t *v)
  55. {
  56. // returns (--*v==0)
  57. return (__sync_add_and_fetch(&v->counter,-1)==0);
  58. }
  59. static __inline__ bool atomic_inc_and_test(atomic_t *v)
  60. {
  61. // returns (++*v==0)
  62. return (__sync_add_and_fetch(&v->counter,1)==0);
  63. }
  64. static __inline__ void atomic_inc(atomic_t *v)
  65. {
  66. // (*v)++
  67. __sync_add_and_fetch(&v->counter,1);
  68. }
  69. static __inline__ void atomic_dec(atomic_t *v)
  70. {
  71. // (*v)--
  72. __sync_add_and_fetch(&v->counter,-1);
  73. }
  74. static __inline__ int atomic_xchg(int i, atomic_t *v)
  75. {
  76. // int ret = *v; *v = i; return v;
  77. return __sync_lock_test_and_set(&v->counter,i); // actually an xchg
  78. }
  79. static __inline__ void atomic_add(atomic_t *v,int i)
  80. {
  81. // (*v)+=i;
  82. __sync_add_and_fetch(&v->counter,i);
  83. }
  84. static __inline__ int atomic_add_exchange(atomic_t *v,int i)
  85. {
  86. // int ret = *v; (*v) += i; return ret;
  87. return __sync_fetch_and_add(&v->counter,i);
  88. }
  89. static __inline__ bool atomic_cas(atomic_t *v,int newvalue, int expectedvalue)
  90. {
  91. // bool ret = (*v==expectedvalue); if (ret) *v = newvalue; return ret;
  92. return __sync_bool_compare_and_swap(&v->counter, expectedvalue, newvalue);
  93. }
  94. static __inline__ void * atomic_xchg_ptr(void *p, void **v)
  95. {
  96. // void * ret = *v; (*v) = p; return ret;
  97. return (void *)__sync_lock_test_and_set((memsize_t *)v,(memsize_t)p);
  98. }
  99. static __inline__ bool atomic_cas_ptr(void **v,void *newvalue, void *expectedvalue)
  100. {
  101. // bool ret = (*v==expectedvalue); if (ret) *v = newvalue; return ret;
  102. return __sync_bool_compare_and_swap((memsize_t *)v, (memsize_t)expectedvalue, (memsize_t)newvalue);
  103. }
  104. #else // other unix
  105. //Truely awful implementations of atomic operations...
  106. typedef volatile int atomic_t;
  107. bool jlib_decl poor_atomic_dec_and_test(atomic_t * v);
  108. bool jlib_decl poor_atomic_inc_and_test(atomic_t * v);
  109. int jlib_decl poor_atomic_xchg(int i, atomic_t * v);
  110. void jlib_decl poor_atomic_add(atomic_t * v, int i);
  111. int jlib_decl poor_atomic_add_exchange(atomic_t * v, int i);
  112. bool jlib_decl poor_atomic_cas(atomic_t * v, int newvalue, int expectedvalue);
  113. void jlib_decl *poor_atomic_xchg_ptr(void *p, void **v);
  114. bool jlib_decl poor_atomic_cas_ptr(void ** v, void *newvalue, void *expectedvalue);
  115. #define ATOMIC_INIT(i) (i)
  116. #define atomic_inc(v) (void)poor_atomic_inc_and_test(v)
  117. #define atomic_inc_and_test(v) poor_atomic_inc_and_test(v)
  118. #define atomic_dec(v) (void)poor_atomic_dec_and_test(v)
  119. #define atomic_dec_and_test(v) poor_atomic_dec_and_test(v)
  120. #define atomic_read(v) (*v)
  121. #define atomic_set(v,i) ((*v) = (i))
  122. #define atomic_xchg(i, v) poor_atomic_xchg(i, v)
  123. #define atomic_add(v,i) poor_atomic_add(v, i)
  124. #define atomic_add_exchange(v, i) poor_atomic_add_exchange(v, i)
  125. #define atomic_cas(v,newvalue,expectedvalue) poor_atomic_cas(v,newvalue,expectedvalue)
  126. #define atomic_xchg_ptr(p, v) poor_atomic_xchg_ptr(p, v)
  127. #define atomic_cas_ptr(v,newvalue,expectedvalue) poor_atomic_cas_ptr(v,newvalue,expectedvalue)
  128. #endif
  129. #endif