(file) Return to atomic.h CVS log (file) (dir) Up to [OMI] / omi / pal

  1 krisbash 1.1 #ifndef _pal_atomic_h
  2              #define _pal_atomic_h
  3              
  4              #ifdef _MSC_VER
  5              #pragma prefast(push)
  6              #pragma prefast(disable:28251)
  7              #pragma prefast(disable:28252)
  8              #pragma prefast(disable:28253)
  9              #include <intrin.h>
 10              #pragma prefast(pop)
 11              #endif
 12              
 13              #include <pal/palcommon.h>
 14              
 15              #if !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
 16              #if defined(PAL_HAVE_PTHREADS)
 17              # include <pthread.h>
 18              #endif
 19              #if defined(PAL_HAVE_POSIX)
 20              # include <sys/types.h>
 21              # include <unistd.h>
 22 krisbash 1.1 #endif
 23              #endif
 24              
 25              PAL_BEGIN_EXTERNC
 26              
 27              #if !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
 28              
 29              #define PAL_ATOMIC_LOCKS_SIZE 64
 30              
 31              extern PAL_Boolean __palInitialized;
 32              extern pthread_mutex_t __atomicInitLock;
 33              extern pthread_mutex_t __atomicLocks[PAL_ATOMIC_LOCKS_SIZE];
 34              
 35              PAL_INLINE void __AcquireLock(pthread_mutex_t *lock);
 36              PAL_INLINE void __ReleaseLock(pthread_mutex_t *lock);
 37              
 38              PAL_INLINE void __ForkHandlerHelper(PAL_Boolean acquire)
 39              {
 40                  int i = 0;
 41                  for(i = 0; i < PAL_ATOMIC_LOCKS_SIZE; i++)
 42                  {
 43 krisbash 1.1         if(acquire)
 44                          __AcquireLock(&(__atomicLocks[i]));
 45                      else
 46                          __ReleaseLock(&(__atomicLocks[i]));
 47                  }
 48              
 49                  if(acquire)
 50                  {
 51                      pthread_mutex_lock(&__atomicInitLock);
 52                  }
 53                  else
 54                  {
 55                      pthread_mutex_unlock(&__atomicInitLock);
 56                  }
 57              }
 58              
 59              PAL_INLINE void __PrepareForkHandler(void)
 60              {
 61                  __ForkHandlerHelper(PAL_TRUE);
 62              }
 63              
 64 krisbash 1.1 PAL_INLINE void __ParentForkHandler(void)
 65              {
 66                  __ForkHandlerHelper(PAL_FALSE);
 67              }
 68              
 69              PAL_INLINE void __ChildForkHandler(void)
 70              {
 71                  __ForkHandlerHelper(PAL_FALSE);
 72              }
 73              
 74              PAL_INLINE void __AcquireLock(pthread_mutex_t *lock)
 75              {
 76                  if(__palInitialized == PAL_FALSE)
 77                  {
 78                      pthread_mutex_lock(&__atomicInitLock);
 79              
 80                      if(__palInitialized == PAL_FALSE)
 81                      {
 82                          pthread_atfork(__PrepareForkHandler, __ParentForkHandler, __ChildForkHandler);
 83                          __palInitialized = PAL_TRUE;
 84                      }
 85 krisbash 1.1 
 86                      pthread_mutex_unlock(&__atomicInitLock);
 87                  }
 88              
 89                  pthread_mutex_lock(lock);
 90              }
 91              
 92              PAL_INLINE void __ReleaseLock(pthread_mutex_t *lock)
 93              {
 94                  pthread_mutex_unlock(lock);
 95              }
 96              
 97              #define __AtomicLockToUse(x) (&(__atomicLocks[(((unsigned)(((ptrdiff_t)(x)) >> 2)) % PAL_ATOMIC_LOCKS_SIZE)]))
 98              
 99              PAL_INLINE void __AcquireAtomicLock(_In_ volatile ptrdiff_t* x)
100              {        
101                  __AcquireLock(__AtomicLockToUse(x));
102              }
103              
104              PAL_INLINE void __ReleaseAtomicLock(_In_ volatile ptrdiff_t* x)
105              {
106 krisbash 1.1     __ReleaseLock(__AtomicLockToUse(x));
107              }
108              
109              #endif
110              
111              PAL_INLINE ptrdiff_t Atomic_Read(
112                  _Inout_ volatile ptrdiff_t* x)
113              {
114              #if defined(_MSC_VER)
115                  return *x;
116              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
117                  ptrdiff_t retVal = 0;
118                  __AcquireAtomicLock(x);
119                  retVal = *x;
120                  __ReleaseAtomicLock(x);
121                  return retVal;
122              #else
123                  return __sync_add_and_fetch(x, 0);
124              #endif
125              }
126              
127 krisbash 1.1 
128              PAL_INLINE ptrdiff_t Atomic_Inc(
129                  _Inout_ volatile ptrdiff_t* x)
130              {
131              #if defined(_MSC_VER)
132              # if defined(_WIN64)
133                  return InterlockedIncrement64(x);
134              # else
135                  return InterlockedIncrement((volatile long *)x);
136              # endif
137              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
138                  ptrdiff_t retVal = 0;
139                  __AcquireAtomicLock(x);
140                  retVal = *x; 
141                  retVal++; 
142                  *x = retVal;
143                  __ReleaseAtomicLock(x);
144                  return retVal;
145              #else
146                  return __sync_add_and_fetch(x, 1);
147              #endif
148 krisbash 1.1 }
149              
150              PAL_INLINE ptrdiff_t Atomic_Dec(
151                  _Inout_ volatile ptrdiff_t* x)
152              {
153              #if defined(_MSC_VER)
154              # if defined(_WIN64)
155                  return InterlockedDecrement64(x);
156              # else
157                  return InterlockedDecrement((volatile long *)x);
158              # endif
159              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
160                  ptrdiff_t retVal = 0;
161                  __AcquireAtomicLock(x);
162                  retVal = *x; 
163                  retVal--; 
164                  *x = retVal;
165                  __ReleaseAtomicLock(x);
166                  return retVal;
167              #else
168                  return __sync_sub_and_fetch(x, 1);
169 krisbash 1.1 #endif
170              }
171              
172              PAL_INLINE ptrdiff_t Atomic_CompareAndSwap(
173                  _Inout_ volatile ptrdiff_t* dest,
174                  _In_ ptrdiff_t comparand,
175                  _In_ ptrdiff_t newValue)
176              {
177              #if defined(_MSC_VER)
178                  return (ptrdiff_t)InterlockedCompareExchangePointer(
179                      (PVOID*)dest, (PVOID)newValue, (PVOID)comparand);
180              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
181                  ptrdiff_t retVal = 0;
182                  __AcquireAtomicLock(dest);
183                  retVal = *dest;
184                  if(retVal == comparand)
185                  {
186                      *dest = newValue;
187                  }        
188                  __ReleaseAtomicLock(dest);
189                  return retVal;
190 krisbash 1.1 #else
191                  return __sync_val_compare_and_swap(dest, comparand, newValue);
192              #endif
193              }
194              
195              PAL_INLINE ptrdiff_t Atomic_Swap(
196                  _Inout_ volatile ptrdiff_t* dest,
197                  _In_ ptrdiff_t newValue)
198              {
199              #if defined(_MSC_VER)
200                  return (ptrdiff_t)InterlockedExchangePointer((PVOID*)dest, (PVOID)newValue);
201              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
202                  ptrdiff_t retVal = 0;
203                  __AcquireAtomicLock(dest);
204                  retVal = *dest;    
205                  *dest = newValue;    
206                  __ReleaseAtomicLock(dest);
207                  return retVal;
208              #else
209                  return __sync_lock_test_and_set(dest, newValue);
210              #endif
211 krisbash 1.1 }
212              
213              PAL_INLINE ptrdiff_t Atomic_Add(
214                  _Inout_ volatile ptrdiff_t* x,
215                          ptrdiff_t value)
216              {
217              #if defined(_MSC_VER)
218              # if defined(_WIN64)
219                  return InterlockedAdd64(x, value);
220              # else
221                  return InterlockedExchangeAdd((volatile long *)x, value) + value;
222              # endif
223              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
224                  ptrdiff_t retVal = 0;
225                  __AcquireAtomicLock(x);
226                  retVal = *x; 
227                  retVal = retVal + value; 
228                  *x = retVal;    
229                  __ReleaseAtomicLock(x);
230                  return retVal;
231              #else
232 krisbash 1.1     return __sync_add_and_fetch(x, value);
233              #endif
234              }
235              
236              PAL_INLINE ptrdiff_t Atomic_And(
237                  _Inout_ volatile ptrdiff_t* x,
238                                   ptrdiff_t value)
239              {
240              #if defined(_MSC_VER)
241              # if defined(_WIN64)
242                  return _InterlockedAnd64(x, value) & value;
243              # else
244                  return _InterlockedAnd((volatile long *)x, value) & value;
245              # endif
246              #elif !defined(CONFIG_HAVE_ATOMIC_INTRINSICS)
247                  ptrdiff_t retVal = 0;
248                  __AcquireAtomicLock(x);
249                  retVal = *x; 
250                  retVal = retVal & value; 
251                  *x = retVal;           
252                  __ReleaseAtomicLock(x);
253 krisbash 1.1     return retVal;
254              #else
255                  return __sync_and_and_fetch(x, value);
256              #endif
257              }
258              
259              /*
260              **==============================================================================
261              **
262              ** NonX86MemoryBarrier macro
263              **
264              **==============================================================================
265              */
266              #ifdef _MSC_VER
267              # if defined(_M_IX86) || defined(_M_AMD64)
268              #  define NonX86MemoryBarrier() ((void)0)
269              # else
270              #  define NonX86MemoryBarrier() MemoryBarrier()
271              # endif
272              #else /* !defined(_MSC_VER) */
273              # if defined(__i386__) || defined(__amd64__)
274 krisbash 1.1 #  define NonX86MemoryBarrier() ((void)0)
275              # elif defined(CONFIG_HAVE_SYNC_SYNCHRONIZE)
276              #  define NonX86MemoryBarrier() __sync_synchronize()
277              # else
278              extern volatile ptrdiff_t __memoryBarrierVar;
279              #  define NonX86MemoryBarrier() ((void)Atomic_Swap(&__memoryBarrierVar, 0))
280              # endif
281              #endif
282              
283              PAL_END_EXTERNC
284              
285              #endif /* _pal_atomic_h */

ViewCVS 0.9.2