nsprpub/pr/include/pratom.h

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial