atomic_ops_stack.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * The implementation of the routines described here is covered by the GPL.
  3. * This header file is covered by the following license:
  4. */
  5. /*
  6. * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. * SOFTWARE.
  25. */
  26. /* Almost lock-free LIFO linked lists (linked stacks). */
  27. #ifndef AO_STACK_H
  28. #define AO_STACK_H
  29. #include "atomic_ops.h"
  30. #if !defined(AO_HAVE_compare_double_and_swap_double) \
  31. && !defined(AO_HAVE_compare_double_and_swap) \
  32. && defined(AO_HAVE_compare_and_swap)
  33. # define AO_USE_ALMOST_LOCK_FREE
  34. #else
  35. /* If we have no compare-and-swap operation defined, we assume */
  36. /* that we will actually be using CAS emulation. If we do that, */
  37. /* it's cheaper to use the version-based implementation. */
  38. # define AO_STACK_IS_LOCK_FREE
  39. #endif
  40. /*
  41. * These are not guaranteed to be completely lock-free.
  42. * List insertion may spin under extremely unlikely conditions.
  43. * It cannot deadlock due to recursive reentry unless AO_list_remove
  44. * is called while at least AO_BL_SIZE activations of
  45. * AO_list_remove are currently active in the same thread, i.e.
  46. * we must have at least AO_BL_SIZE recursive signal handler
  47. * invocations.
  48. *
  49. * All operations take an AO_list_aux argument. It is safe to
  50. * share a single AO_list_aux structure among all lists, but that
  51. * may increase contention. Any given list must always be accessed
  52. * with the same AO_list_aux structure.
  53. *
  54. * We make some machine-dependent assumptions:
  55. * - We have a compare-and-swap operation.
  56. * - At least _AO_N_BITS low order bits in pointers are
  57. * zero and normally unused.
  58. * - size_t and pointers have the same size.
  59. *
  60. * We do use a fully lock-free implementation if double-width
  61. * compare-and-swap operations are available.
  62. */
  63. #ifdef AO_USE_ALMOST_LOCK_FREE
  64. /* The number of low order pointer bits we can use for a small */
  65. /* version number. */
  66. # if defined(__LP64__) || defined(_LP64) || defined(_WIN64)
  67. /* WIN64 isn't really supported yet. */
  68. # define AO_N_BITS 3
  69. # else
  70. # define AO_N_BITS 2
  71. # endif
  72. # define AO_BIT_MASK ((1 << AO_N_BITS) - 1)
  73. /*
  74. * AO_stack_aux should be treated as opaque.
  75. * It is fully defined here, so it can be allocated, and to facilitate
  76. * debugging.
  77. */
  78. #ifndef AO_BL_SIZE
  79. # define AO_BL_SIZE 2
  80. #endif
  81. #if AO_BL_SIZE > (1 << AO_N_BITS)
  82. # error AO_BL_SIZE too big
  83. #endif
  84. typedef struct AO__stack_aux {
  85. volatile AO_t AO_stack_bl[AO_BL_SIZE];
  86. } AO_stack_aux;
  87. /* The stack implementation knows only about the location of */
  88. /* link fields in nodes, and nothing about the rest of the */
  89. /* stack elements. Link fields hold an AO_t, which is not */
  90. /* necessarily a real pointer. This converts the AO_t to a */
  91. /* real (AO_t *) which is either o, or points at the link */
  92. /* field in the next node. */
  93. #define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK)
  94. /* The following two routines should not normally be used directly. */
  95. /* We make them visible here for the rare cases in which it makes sense */
  96. /* to share the an AO_stack_aux between stacks. */
  97. void
  98. AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x,
  99. AO_stack_aux *);
  100. AO_t *
  101. AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux *);
  102. /* And now AO_stack_t for the real interface: */
  103. typedef struct AO__stack {
  104. volatile AO_t AO_ptr;
  105. AO_stack_aux AO_aux;
  106. } AO_stack_t;
  107. #define AO_STACK_INITIALIZER {0,{{0}}}
  108. AO_INLINE void AO_stack_init(AO_stack_t *list)
  109. {
  110. # if AO_BL_SIZE == 2
  111. list -> AO_aux.AO_stack_bl[0] = 0;
  112. list -> AO_aux.AO_stack_bl[1] = 0;
  113. # else
  114. int i;
  115. for (i = 0; i < AO_BL_SIZE; ++i)
  116. list -> AO_aux.AO_stack_bl[i] = 0;
  117. # endif
  118. list -> AO_ptr = 0;
  119. }
  120. /* Convert an AO_stack_t to a pointer to the link field in */
  121. /* the first element. */
  122. #define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_ptr)
  123. #define AO_stack_push_release(l, e) \
  124. AO_stack_push_explicit_aux_release(&((l)->AO_ptr), e, &((l)->AO_aux))
  125. #define AO_HAVE_stack_push_release
  126. #define AO_stack_pop_acquire(l) \
  127. AO_stack_pop_explicit_aux_acquire(&((l)->AO_ptr), &((l)->AO_aux))
  128. #define AO_HAVE_stack_pop_acquire
  129. # else /* Use fully non-blocking data structure, wide CAS */
  130. #ifndef AO_HAVE_double_t
  131. /* Can happen if we're using CAS emulation, since we don't want to */
  132. /* force that here, in case other atomic_ops clients don't want it. */
  133. # include "atomic_ops/sysdeps/standard_ao_double_t.h"
  134. #endif
  135. typedef volatile AO_double_t AO_stack_t;
  136. /* AO_val1 is version, AO_val2 is pointer. */
  137. #define AO_STACK_INITIALIZER AO_DOUBLE_T_INITIALIZER
  138. AO_INLINE void AO_stack_init(AO_stack_t *list)
  139. {
  140. list -> AO_val1 = 0;
  141. list -> AO_val2 = 0;
  142. }
  143. #define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_val2)
  144. #define AO_REAL_NEXT_PTR(x) (AO_t *)(x)
  145. void AO_stack_push_release(AO_stack_t *list, AO_t *new_element);
  146. #define AO_HAVE_stack_push_release
  147. AO_t * AO_stack_pop_acquire(AO_stack_t *list);
  148. #define AO_HAVE_stack_pop_acquire
  149. #endif /* Wide CAS case */
  150. #if defined(AO_HAVE_stack_push_release) && !defined(AO_HAVE_stack_push)
  151. # define AO_stack_push(l, e) AO_stack_push_release(l, e)
  152. # define AO_HAVE_stack_push
  153. #endif
  154. #if defined(AO_HAVE_stack_pop_acquire) && !defined(AO_HAVE_stack_pop)
  155. # define AO_stack_pop(l) AO_stack_pop_acquire(l)
  156. # define AO_HAVE_stack_pop
  157. #endif
  158. #endif /* !AO_STACK_H */