1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/include/pratom.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* GLOBAL FUNCTIONS: 1.10 +** DESCRIPTION: 1.11 +** PR Atomic operations 1.12 +*/ 1.13 + 1.14 +#ifndef pratom_h___ 1.15 +#define pratom_h___ 1.16 + 1.17 +#include "prtypes.h" 1.18 +#include "prlock.h" 1.19 + 1.20 +PR_BEGIN_EXTERN_C 1.21 + 1.22 +/* 1.23 +** FUNCTION: PR_AtomicIncrement 1.24 +** DESCRIPTION: 1.25 +** Atomically increment a 32 bit value. 1.26 +** INPUTS: 1.27 +** val: a pointer to the value to increment 1.28 +** RETURN: 1.29 +** the returned value is the result of the increment 1.30 +*/ 1.31 +NSPR_API(PRInt32) PR_AtomicIncrement(PRInt32 *val); 1.32 + 1.33 +/* 1.34 +** FUNCTION: PR_AtomicDecrement 1.35 +** DESCRIPTION: 1.36 +** Atomically decrement a 32 bit value. 1.37 +** INPUTS: 1.38 +** val: a pointer to the value to decrement 1.39 +** RETURN: 1.40 +** the returned value is the result of the decrement 1.41 +*/ 1.42 +NSPR_API(PRInt32) PR_AtomicDecrement(PRInt32 *val); 1.43 + 1.44 +/* 1.45 +** FUNCTION: PR_AtomicSet 1.46 +** DESCRIPTION: 1.47 +** Atomically set a 32 bit value. 1.48 +** INPUTS: 1.49 +** val: A pointer to a 32 bit value to be set 1.50 +** newval: The newvalue to assign to val 1.51 +** RETURN: 1.52 +** Returns the prior value 1.53 +*/ 1.54 +NSPR_API(PRInt32) PR_AtomicSet(PRInt32 *val, PRInt32 newval); 1.55 + 1.56 +/* 1.57 +** FUNCTION: PR_AtomicAdd 1.58 +** DESCRIPTION: 1.59 +** Atomically add a 32 bit value. 1.60 +** INPUTS: 1.61 +** ptr: a pointer to the value to increment 1.62 +** val: value to be added 1.63 +** RETURN: 1.64 +** the returned value is the result of the addition 1.65 +*/ 1.66 +NSPR_API(PRInt32) PR_AtomicAdd(PRInt32 *ptr, PRInt32 val); 1.67 + 1.68 +/* 1.69 +** MACRO: PR_ATOMIC_INCREMENT 1.70 +** MACRO: PR_ATOMIC_DECREMENT 1.71 +** MACRO: PR_ATOMIC_SET 1.72 +** MACRO: PR_ATOMIC_ADD 1.73 +** DESCRIPTION: 1.74 +** Macro versions of the atomic operations. They may be implemented 1.75 +** as compiler intrinsics. 1.76 +** 1.77 +** IMPORTANT NOTE TO NSPR MAINTAINERS: 1.78 +** Implement these macros with compiler intrinsics only on platforms 1.79 +** where the PR_AtomicXXX functions are truly atomic (i.e., where the 1.80 +** configuration macro _PR_HAVE_ATOMIC_OPS is defined). Otherwise, 1.81 +** the macros and functions won't be compatible and can't be used 1.82 +** interchangeably. 1.83 +*/ 1.84 +#if defined(_WIN32) && !defined(_WIN32_WCE) && \ 1.85 + (!defined(_MSC_VER) || (_MSC_VER >= 1310)) 1.86 + 1.87 +long __cdecl _InterlockedIncrement(long volatile *Addend); 1.88 +long __cdecl _InterlockedDecrement(long volatile *Addend); 1.89 +long __cdecl _InterlockedExchange(long volatile *Target, long Value); 1.90 +long __cdecl _InterlockedExchangeAdd(long volatile *Addend, long Value); 1.91 + 1.92 +#ifdef _MSC_VER 1.93 +#pragma intrinsic(_InterlockedIncrement) 1.94 +#pragma intrinsic(_InterlockedDecrement) 1.95 +#pragma intrinsic(_InterlockedExchange) 1.96 +#pragma intrinsic(_InterlockedExchangeAdd) 1.97 +#endif 1.98 + 1.99 +#define PR_ATOMIC_INCREMENT(val) _InterlockedIncrement((long volatile *)(val)) 1.100 +#define PR_ATOMIC_DECREMENT(val) _InterlockedDecrement((long volatile *)(val)) 1.101 +#define PR_ATOMIC_SET(val, newval) \ 1.102 + _InterlockedExchange((long volatile *)(val), (long)(newval)) 1.103 +#define PR_ATOMIC_ADD(ptr, val) \ 1.104 + (_InterlockedExchangeAdd((long volatile *)(ptr), (long)(val)) + (val)) 1.105 + 1.106 +#elif ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && \ 1.107 + ((defined(__APPLE__) && \ 1.108 + (defined(__ppc__) || defined(__i386__) || defined(__x86_64__))) || \ 1.109 + (defined(__linux__) && \ 1.110 + ((defined(__i386__) && \ 1.111 + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \ 1.112 + defined(__ia64__) || defined(__x86_64__) || \ 1.113 + defined(__powerpc__) || \ 1.114 + (defined(__arm__) && \ 1.115 + defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)) || \ 1.116 + defined(__aarch64__) || defined(__alpha)))) 1.117 + 1.118 +/* 1.119 + * Because the GCC manual warns that some processors may support 1.120 + * reduced functionality of __sync_lock_test_and_set, we test for the 1.121 + * processors that we believe support a full atomic exchange operation. 1.122 + */ 1.123 + 1.124 +#define PR_ATOMIC_INCREMENT(val) __sync_add_and_fetch(val, 1) 1.125 +#define PR_ATOMIC_DECREMENT(val) __sync_sub_and_fetch(val, 1) 1.126 +#define PR_ATOMIC_SET(val, newval) __sync_lock_test_and_set(val, newval) 1.127 +#define PR_ATOMIC_ADD(ptr, val) __sync_add_and_fetch(ptr, val) 1.128 + 1.129 +#else 1.130 + 1.131 +#define PR_ATOMIC_INCREMENT(val) PR_AtomicIncrement(val) 1.132 +#define PR_ATOMIC_DECREMENT(val) PR_AtomicDecrement(val) 1.133 +#define PR_ATOMIC_SET(val, newval) PR_AtomicSet(val, newval) 1.134 +#define PR_ATOMIC_ADD(ptr, val) PR_AtomicAdd(ptr, val) 1.135 + 1.136 +#endif 1.137 + 1.138 +/* 1.139 +** LIFO linked-list (stack) 1.140 +*/ 1.141 +typedef struct PRStackElemStr PRStackElem; 1.142 + 1.143 +struct PRStackElemStr { 1.144 + PRStackElem *prstk_elem_next; /* next pointer MUST be at offset 0; 1.145 + assembly language code relies on this */ 1.146 +}; 1.147 + 1.148 +typedef struct PRStackStr PRStack; 1.149 + 1.150 +/* 1.151 +** FUNCTION: PR_CreateStack 1.152 +** DESCRIPTION: 1.153 +** Create a stack, a LIFO linked list 1.154 +** INPUTS: 1.155 +** stack_name: a pointer to string containing the name of the stack 1.156 +** RETURN: 1.157 +** A pointer to the created stack, if successful, else NULL. 1.158 +*/ 1.159 +NSPR_API(PRStack *) PR_CreateStack(const char *stack_name); 1.160 + 1.161 +/* 1.162 +** FUNCTION: PR_StackPush 1.163 +** DESCRIPTION: 1.164 +** Push an element on the top of the stack 1.165 +** INPUTS: 1.166 +** stack: pointer to the stack 1.167 +** stack_elem: pointer to the stack element 1.168 +** RETURN: 1.169 +** None 1.170 +*/ 1.171 +NSPR_API(void) PR_StackPush(PRStack *stack, PRStackElem *stack_elem); 1.172 + 1.173 +/* 1.174 +** FUNCTION: PR_StackPop 1.175 +** DESCRIPTION: 1.176 +** Remove the element on the top of the stack 1.177 +** INPUTS: 1.178 +** stack: pointer to the stack 1.179 +** RETURN: 1.180 +** A pointer to the stack element removed from the top of the stack, 1.181 +** if non-empty, 1.182 +** else NULL 1.183 +*/ 1.184 +NSPR_API(PRStackElem *) PR_StackPop(PRStack *stack); 1.185 + 1.186 +/* 1.187 +** FUNCTION: PR_DestroyStack 1.188 +** DESCRIPTION: 1.189 +** Destroy the stack 1.190 +** INPUTS: 1.191 +** stack: pointer to the stack 1.192 +** RETURN: 1.193 +** PR_SUCCESS - if successfully deleted 1.194 +** PR_FAILURE - if the stack is not empty 1.195 +** PR_GetError will return 1.196 +** PR_INVALID_STATE_ERROR - stack is not empty 1.197 +*/ 1.198 +NSPR_API(PRStatus) PR_DestroyStack(PRStack *stack); 1.199 + 1.200 +PR_END_EXTERN_C 1.201 + 1.202 +#endif /* pratom_h___ */