/vendor/gc/libatomic_ops-1.2/src/atomic_ops.h

http://github.com/feyeleanor/RubyGoLightly · C++ Header · 300 lines · 128 code · 21 blank · 151 comment · 39 complexity · 1974cb5b0bbc57256091ae4d8f87042c MD5 · raw file

  1. /*
  2. * Copyright (c) 2003 Hewlett-Packard Development Company, L.P.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. * SOFTWARE.
  21. */
  22. #ifndef ATOMIC_OPS_H
  23. #define ATOMIC_OPS_H
  24. #include <assert.h>
  25. #include <stddef.h>
  26. /* We define various atomic operations on memory in a */
  27. /* machine-specific way. Unfortunately, this is complicated */
  28. /* by the fact that these may or may not be combined with */
  29. /* various memory barriers. Thus the actual operations we */
  30. /* define have the form AO_<atomic-op>_<barrier>, for all */
  31. /* plausible combinations of <atomic-op> and <barrier>. */
  32. /* This of course results in a mild combinatorial explosion. */
  33. /* To deal with it, we try to generate derived */
  34. /* definitions for as many of the combinations as we can, as */
  35. /* automatically as possible. */
  36. /* */
  37. /* Our assumption throughout is that the programmer will */
  38. /* specify the least demanding operation and memory barrier */
  39. /* that will guarantee correctness for the implementation. */
  40. /* Our job is to find the least expensive way to implement it */
  41. /* on the applicable hardware. In many cases that will */
  42. /* involve, for example, a stronger memory barrier, or a */
  43. /* combination of hardware primitives. */
  44. /* */
  45. /* Conventions: */
  46. /* "plain" atomic operations are not guaranteed to include */
  47. /* a barrier. The suffix in the name specifies the barrier */
  48. /* type. Suffixes are: */
  49. /* _release: Earlier operations may not be delayed past it. */
  50. /* _acquire: Later operations may not move ahead of it. */
  51. /* _read: Subsequent reads must follow this operation and */
  52. /* preceding reads. */
  53. /* _write: Earlier writes precede both this operation and */
  54. /* later writes. */
  55. /* _full: Ordered with respect to both earlier and later memops.*/
  56. /* _release_write: Ordered with respect to earlier writes. */
  57. /* _acquire_read: Ordered with repsect to later reads. */
  58. /* */
  59. /* Currently we try to define the following atomic memory */
  60. /* operations, in combination with the above barriers: */
  61. /* AO_nop */
  62. /* AO_load */
  63. /* AO_store */
  64. /* AO_test_and_set (binary) */
  65. /* AO_fetch_and_add */
  66. /* AO_fetch_and_add1 */
  67. /* AO_fetch_and_sub1 */
  68. /* AO_or */
  69. /* AO_compare_and_swap */
  70. /* */
  71. /* Note that atomicity guarantees are valid only if both */
  72. /* readers and writers use AO_ operations to access the */
  73. /* shared value, while ordering constraints are intended to */
  74. /* apply all memory operations. If a location can potentially */
  75. /* be accessed simultaneously from multiple threads, and one of */
  76. /* those accesses may be a write access, then all such */
  77. /* accesses to that location should be through AO_ primitives. */
  78. /* However if AO_ operations enforce sufficient ordering to */
  79. /* ensure that a location x cannot be accessed concurrently, */
  80. /* or can only be read concurrently, then x can be accessed */
  81. /* via ordinary references and assignments. */
  82. /* */
  83. /* Compare_and_exchange takes an address and an expected old */
  84. /* value and a new value, and returns an int. Nonzero */
  85. /* indicates that it succeeded. */
  86. /* Test_and_set takes an address, atomically replaces it by */
  87. /* AO_TS_SET, and returns the prior value. */
  88. /* An AO_TS_t location can be reset with the */
  89. /* AO_CLEAR macro, which normally uses AO_store_release. */
  90. /* AO_fetch_and_add takes an address and an AO_t increment */
  91. /* value. The AO_fetch_and_add1 and AO_fetch_and_sub1 variants */
  92. /* are provided, since they allow faster implementations on */
  93. /* some hardware. AO_or atomically ors an AO_t value into a */
  94. /* memory location, but does not provide access to the original.*/
  95. /* */
  96. /* We expect this list to grow slowly over time. */
  97. /* */
  98. /* Note that AO_nop_full is a full memory barrier. */
  99. /* */
  100. /* Note that if some data is initialized with */
  101. /* data.x = ...; data.y = ...; ... */
  102. /* AO_store_release_write(&data_is_initialized, 1) */
  103. /* then data is guaranteed to be initialized after the test */
  104. /* if (AO_load_release_read(&data_is_initialized)) ... */
  105. /* succeeds. Furthermore, this should generate near-optimal */
  106. /* code on all common platforms. */
  107. /* */
  108. /* All operations operate on unsigned AO_t, which */
  109. /* is the natural word size, and usually unsigned long. */
  110. /* It is possible to check whether a particular operation op */
  111. /* is available on a particular platform by checking whether */
  112. /* AO_HAVE_op is defined. We make heavy use of these macros */
  113. /* internally. */
  114. /* The rest of this file basically has three sections: */
  115. /* */
  116. /* Some utility and default definitions. */
  117. /* */
  118. /* The architecture dependent section: */
  119. /* This defines atomic operations that have direct hardware */
  120. /* support on a particular platform, mostly by uncluding the */
  121. /* appropriate compiler- and hardware-dependent file. */
  122. /* */
  123. /* The synthesis section: */
  124. /* This tries to define other atomic operations in terms of */
  125. /* those that are explicitly available on the platform. */
  126. /* This section is hardware independent. */
  127. /* We make no attempt to synthesize operations in ways that */
  128. /* effectively introduce locks, except for the debugging/demo */
  129. /* pthread-based implementation at the beginning. A more */
  130. /* relistic implementation that falls back to locks could be */
  131. /* added as a higher layer. But that would sacrifice */
  132. /* usability from signal handlers. */
  133. /* The synthesis section is implemented almost entirely in */
  134. /* atomic_ops_generalize.h. */
  135. /* Some common defaults. Overridden for some architectures. */
  136. #define AO_t size_t
  137. /* The test_and_set primitive returns an AO_TS_VAL_t value. */
  138. /* AO_TS_t is the type of an in-memory test-and-set location. */
  139. #define AO_TS_INITIALIZER (AO_t)AO_TS_CLEAR
  140. /* Platform-dependent stuff: */
  141. #if defined(__GNUC__) || defined(_MSC_VER) || defined(__INTEL_COMPILER)
  142. # define AO_INLINE static __inline
  143. #else
  144. # define AO_INLINE static
  145. #endif
  146. #if defined(__GNUC__) && !defined(__INTEL_COMPILER)
  147. # define AO_compiler_barrier() __asm__ __volatile__("" : : : "memory")
  148. #elif defined(_MSC_VER)
  149. # if defined(_AMD64_)
  150. # pragma intrinsic(_ReadWriteBarrier)
  151. # define AO_compiler_barrier() _ReadWriteBarrier()
  152. /* We assume this does not generate a fence instruction. */
  153. /* The documentation is a bit unclear. */
  154. # else
  155. # define AO_compiler_barrier() __asm { }
  156. /* The preceding implementation may be preferable here too. */
  157. /* But the documentation warns about VC++ 2003 and earlier. */
  158. # endif
  159. #elif defined(__INTEL_COMPILER)
  160. # define AO_compiler_barrier() __memory_barrier() /* Too strong? IA64-only? */
  161. #elif defined(_HPUX_SOURCE)
  162. # if defined(__ia64)
  163. # include <machine/sys/inline.h>
  164. # define AO_compiler_barrier() _Asm_sched_fence()
  165. # else
  166. /* FIXME - We dont know how to do this. This is a guess. */
  167. /* And probably a bad one. */
  168. static volatile int AO_barrier_dummy;
  169. # define AO_compiler_barrier() AO_barrier_dummy = AO_barrier_dummy
  170. # endif
  171. #else
  172. /* We conjecture that the following usually gives us the right */
  173. /* semantics or an error. */
  174. # define AO_compiler_barrier() asm("")
  175. #endif
  176. #if defined(AO_USE_PTHREAD_DEFS)
  177. # include "atomic_ops/sysdeps/generic_pthread.h"
  178. #endif /* AO_USE_PTHREAD_DEFS */
  179. #if defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS) \
  180. && !defined(__INTEL_COMPILER)
  181. # if defined(__i386__)
  182. # include "atomic_ops/sysdeps/gcc/x86.h"
  183. # endif /* __i386__ */
  184. # if defined(__x86_64__)
  185. # include "atomic_ops/sysdeps/gcc/x86_64.h"
  186. # endif /* __i386__ */
  187. # if defined(__ia64__)
  188. # include "atomic_ops/sysdeps/gcc/ia64.h"
  189. # define AO_GENERALIZE_TWICE
  190. # endif /* __ia64__ */
  191. # if defined(__hppa__)
  192. # include "atomic_ops/sysdeps/gcc/hppa.h"
  193. # define AO_CAN_EMUL_CAS
  194. # endif /* __hppa__ */
  195. # if defined(__alpha__)
  196. # include "atomic_ops/sysdeps/gcc/alpha.h"
  197. # define AO_GENERALIZE_TWICE
  198. # endif /* __alpha__ */
  199. # if defined(__s390__)
  200. # include "atomic_ops/sysdeps/gcc/s390.h"
  201. # endif /* __s390__ */
  202. # if defined(__sparc__)
  203. # include "atomic_ops/sysdeps/gcc/sparc.h"
  204. # define AO_CAN_EMUL_CAS
  205. # endif /* __sparc__ */
  206. # if defined(__m68k__)
  207. # include "atomic_ops/sysdeps/gcc/m68k.h"
  208. # endif /* __m68k__ */
  209. # if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \
  210. || defined(__powerpc64__) || defined(__ppc64__)
  211. # include "atomic_ops/sysdeps/gcc/powerpc.h"
  212. # endif /* __powerpc__ */
  213. # if defined(__arm__) && !defined(AO_USE_PTHREAD_DEFS)
  214. # include "atomic_ops/sysdeps/gcc/arm.h"
  215. # define AO_CAN_EMUL_CAS
  216. # endif /* __arm__ */
  217. # if defined(__cris__) || defined(CRIS)
  218. # include "atomic_ops/sysdeps/gcc/cris.h"
  219. # endif
  220. #endif /* __GNUC__ && !AO_USE_PTHREAD_DEFS */
  221. #if defined(__INTEL_COMPILER) && !defined(AO_USE_PTHREAD_DEFS)
  222. # if defined(__ia64__)
  223. # include "atomic_ops/sysdeps/icc/ia64.h"
  224. # define AO_GENERALIZE_TWICE
  225. # endif
  226. #endif
  227. #if defined(_HPUX_SOURCE) && !defined(__GNUC__) && !defined(AO_USE_PTHREAD_DEFS)
  228. # if defined(__ia64)
  229. # include "atomic_ops/sysdeps/hpc/ia64.h"
  230. # define AO_GENERALIZE_TWICE
  231. # else
  232. # include "atomic_ops/sysdeps/hpc/hppa.h"
  233. # define AO_CAN_EMUL_CAS
  234. # endif
  235. #endif
  236. #if !defined(__GNUC__) && (defined(sparc) || defined(__sparc)) \
  237. && !defined(AO_USE_PTHREAD_DEFS)
  238. # include "atomic_ops/sysdeps/sunc/sparc.h"
  239. # define AO_CAN_EMUL_CAS
  240. #endif
  241. #if defined(_MSC_VER)
  242. # if defined(_AMD64_)
  243. # include "atomic_ops/sysdeps/msftc/x86_64.h"
  244. # elif _M_IX86 >= 400
  245. # include "atomic_ops/sysdeps/msftc/x86.h"
  246. # endif
  247. #endif
  248. #if defined(AO_REQUIRE_CAS) && !defined(AO_HAVE_compare_and_swap) \
  249. && !defined(AO_HAVE_compare_and_swap_full) \
  250. && !defined(AO_HAVE_compare_and_swap_acquire)
  251. # if defined(AO_CAN_EMUL_CAS)
  252. # include "atomic_ops/sysdeps/emul_cas.h"
  253. # else
  254. # error Cannot implement AO_compare_and_swap_full on this architecture.
  255. # endif
  256. #endif /* AO_REQUIRE_CAS && !AO_HAVE_compare_and_swap ... */
  257. /* The most common way to clear a test-and-set location */
  258. /* at the end of a critical section. */
  259. #if AO_AO_TS_T && !defined(AO_CLEAR)
  260. # define AO_CLEAR(addr) AO_store_release((AO_TS_t *)addr, AO_TS_CLEAR)
  261. #endif
  262. #if AO_CHAR_TS_T && !defined(AO_CLEAR)
  263. # define AO_CLEAR(addr) AO_char_store_release((AO_TS_t *)addr, AO_TS_CLEAR)
  264. #endif
  265. /*
  266. * The generalization section.
  267. * Theoretically this should repeatedly include atomic_ops_generalize.h.
  268. * In fact, we observe that this converges after a small fixed number
  269. * of iterations, usually one.
  270. */
  271. #include "atomic_ops/generalize.h"
  272. #ifdef AO_GENERALIZE_TWICE
  273. # include "atomic_ops/generalize.h"
  274. #endif
  275. /* For compatibility with version 0.4 and earlier */
  276. #define AO_TS_T AO_TS_t
  277. #define AO_T AO_t
  278. #define AO_TS_VAL AO_TS_VAL_t
  279. #endif /* ATOMIC_OPS_H */