pratom.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /* GLOBAL FUNCTIONS:
  6. ** DESCRIPTION:
  7. ** PR Atomic operations
  8. */
  9. #ifndef pratom_h___
  10. #define pratom_h___
  11. #include "prtypes.h"
  12. #include "prlock.h"
  13. PR_BEGIN_EXTERN_C
  14. /*
  15. ** FUNCTION: PR_AtomicIncrement
  16. ** DESCRIPTION:
  17. ** Atomically increment a 32 bit value.
  18. ** INPUTS:
  19. ** val: a pointer to the value to increment
  20. ** RETURN:
  21. ** the returned value is the result of the increment
  22. */
  23. NSPR_API(PRInt32) PR_AtomicIncrement(PRInt32 *val);
  24. /*
  25. ** FUNCTION: PR_AtomicDecrement
  26. ** DESCRIPTION:
  27. ** Atomically decrement a 32 bit value.
  28. ** INPUTS:
  29. ** val: a pointer to the value to decrement
  30. ** RETURN:
  31. ** the returned value is the result of the decrement
  32. */
  33. NSPR_API(PRInt32) PR_AtomicDecrement(PRInt32 *val);
  34. /*
  35. ** FUNCTION: PR_AtomicSet
  36. ** DESCRIPTION:
  37. ** Atomically set a 32 bit value.
  38. ** INPUTS:
  39. ** val: A pointer to a 32 bit value to be set
  40. ** newval: The newvalue to assign to val
  41. ** RETURN:
  42. ** Returns the prior value
  43. */
  44. NSPR_API(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval);
  45. /*
  46. ** FUNCTION: PR_AtomicAdd
  47. ** DESCRIPTION:
  48. ** Atomically add a 32 bit value.
  49. ** INPUTS:
  50. ** ptr: a pointer to the value to increment
  51. ** val: value to be added
  52. ** RETURN:
  53. ** the returned value is the result of the addition
  54. */
  55. NSPR_API(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val);
  56. /*
  57. ** MACRO: PR_ATOMIC_INCREMENT
  58. ** MACRO: PR_ATOMIC_DECREMENT
  59. ** MACRO: PR_ATOMIC_SET
  60. ** MACRO: PR_ATOMIC_ADD
  61. ** DESCRIPTION:
  62. ** Macro versions of the atomic operations. They may be implemented
  63. ** as compiler intrinsics.
  64. **
  65. ** IMPORTANT NOTE TO NSPR MAINTAINERS:
  66. ** Implement these macros with compiler intrinsics only on platforms
  67. ** where the PR_AtomicXXX functions are truly atomic (i.e., where the
  68. ** configuration macro _PR_HAVE_ATOMIC_OPS is defined). Otherwise,
  69. ** the macros and functions won't be compatible and can't be used
  70. ** interchangeably.
  71. */
  72. #if defined(_WIN32) && !defined(_WIN32_WCE) && \
  73. (!defined(_MSC_VER) || (_MSC_VER >= 1310))
  74. #include <intrin.h>
  75. #ifdef _MSC_VER
  76. #pragma intrinsic(_InterlockedIncrement)
  77. #pragma intrinsic(_InterlockedDecrement)
  78. #pragma intrinsic(_InterlockedExchange)
  79. #pragma intrinsic(_InterlockedExchangeAdd)
  80. #endif
  81. #define PR_ATOMIC_INCREMENT(val) _InterlockedIncrement((long volatile *)(val))
  82. #define PR_ATOMIC_DECREMENT(val) _InterlockedDecrement((long volatile *)(val))
  83. #define PR_ATOMIC_SET(val, newval) \
  84. _InterlockedExchange((long volatile *)(val), (long)(newval))
  85. #define PR_ATOMIC_ADD(ptr, val) \
  86. (_InterlockedExchangeAdd((long volatile *)(ptr), (long)(val)) + (val))
  87. #elif ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && \
  88. ((defined(__APPLE__) && \
  89. (defined(__ppc__) || defined(__i386__) || defined(__x86_64__))) || \
  90. (defined(__linux__) && \
  91. ((defined(__i386__) && \
  92. defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \
  93. defined(__ia64__) || defined(__x86_64__) || \
  94. defined(__powerpc__) || \
  95. (defined(__arm__) && \
  96. defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \
  97. defined(__aarch64__) || defined(__alpha) || \
  98. (defined(__mips__) && \
  99. defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)))))
  100. /*
  101. * Because the GCC manual warns that some processors may support
  102. * reduced functionality of __sync_lock_test_and_set, we test for the
  103. * processors that we believe support a full atomic exchange operation.
  104. */
  105. #define PR_ATOMIC_INCREMENT(val) __sync_add_and_fetch(val, 1)
  106. #define PR_ATOMIC_DECREMENT(val) __sync_sub_and_fetch(val, 1)
  107. #define PR_ATOMIC_SET(val, newval) __sync_lock_test_and_set(val, newval)
  108. #define PR_ATOMIC_ADD(ptr, val) __sync_add_and_fetch(ptr, val)
  109. #else
  110. #define PR_ATOMIC_INCREMENT(val) PR_AtomicIncrement(val)
  111. #define PR_ATOMIC_DECREMENT(val) PR_AtomicDecrement(val)
  112. #define PR_ATOMIC_SET(val, newval) PR_AtomicSet(val, newval)
  113. #define PR_ATOMIC_ADD(ptr, val) PR_AtomicAdd(ptr, val)
  114. #endif
  115. /*
  116. ** LIFO linked-list (stack)
  117. */
  118. typedef struct PRStackElemStr PRStackElem;
  119. struct PRStackElemStr {
  120. PRStackElem *prstk_elem_next; /* next pointer MUST be at offset 0;
  121. assembly language code relies on this */
  122. };
  123. typedef struct PRStackStr PRStack;
  124. /*
  125. ** FUNCTION: PR_CreateStack
  126. ** DESCRIPTION:
  127. ** Create a stack, a LIFO linked list
  128. ** INPUTS:
  129. ** stack_name: a pointer to string containing the name of the stack
  130. ** RETURN:
  131. ** A pointer to the created stack, if successful, else NULL.
  132. */
  133. NSPR_API(PRStack *) PR_CreateStack(const char *stack_name);
  134. /*
  135. ** FUNCTION: PR_StackPush
  136. ** DESCRIPTION:
  137. ** Push an element on the top of the stack
  138. ** INPUTS:
  139. ** stack: pointer to the stack
  140. ** stack_elem: pointer to the stack element
  141. ** RETURN:
  142. ** None
  143. */
  144. NSPR_API(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem);
  145. /*
  146. ** FUNCTION: PR_StackPop
  147. ** DESCRIPTION:
  148. ** Remove the element on the top of the stack
  149. ** INPUTS:
  150. ** stack: pointer to the stack
  151. ** RETURN:
  152. ** A pointer to the stack element removed from the top of the stack,
  153. ** if non-empty,
  154. ** else NULL
  155. */
  156. NSPR_API(PRStackElem *) PR_StackPop(PRStack *stack);
  157. /*
  158. ** FUNCTION: PR_DestroyStack
  159. ** DESCRIPTION:
  160. ** Destroy the stack
  161. ** INPUTS:
  162. ** stack: pointer to the stack
  163. ** RETURN:
  164. ** PR_SUCCESS - if successfully deleted
  165. ** PR_FAILURE - if the stack is not empty
  166. ** PR_GetError will return
  167. ** PR_INVALID_STATE_ERROR - stack is not empty
  168. */
  169. NSPR_API(PRStatus) PR_DestroyStack(PRStack *stack);
  170. PR_END_EXTERN_C
  171. #endif /* pratom_h___ */