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