00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #import "macros.h"
00013
00014 #if defined(OF_THREADS) && !defined(OF_HAVE_GCC_ATOMIC_OPS) && \
00015 !defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00016 # error No atomic operations available!
00017 #endif
00018
00019 #ifdef OF_HAVE_LIBKERN_OSATOMIC_H
00020 # include <libkern/OSAtomic.h>
00021 #endif
00022
00023 static OF_INLINE int32_t
00024 of_atomic_add_32(volatile int32_t *p, int32_t i)
00025 {
00026 #if !defined(OF_THREADS)
00027 return (*p += i);
00028 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00029 return __sync_add_and_fetch(p, i);
00030 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00031 return OSAtomicAdd32Barrier(i, p);
00032 #endif
00033 }
00034
00035 static OF_INLINE int32_t
00036 of_atomic_sub_32(volatile int32_t *p, int32_t i)
00037 {
00038 #if !defined(OF_THREADS)
00039 return (*p -= i);
00040 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00041 return __sync_sub_and_fetch(p, i);
00042 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00043 return OSAtomicAdd32Barrier(-i, p);
00044 #endif
00045 }
00046
00047 static OF_INLINE int32_t
00048 of_atomic_inc_32(volatile int32_t *p)
00049 {
00050 #if !defined(OF_THREADS)
00051 return ++*p;
00052 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00053 return __sync_add_and_fetch(p, 1);
00054 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00055 return OSAtomicIncrement32Barrier(p);
00056 #endif
00057 }
00058
00059 static OF_INLINE int32_t
00060 of_atomic_dec_32(volatile int32_t *p)
00061 {
00062 #if !defined(OF_THREADS)
00063 return --*p;
00064 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00065 return __sync_sub_and_fetch(p, 1);
00066 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00067 return OSAtomicDecrement32Barrier(p);
00068 #endif
00069 }
00070
00071 static OF_INLINE uint32_t
00072 of_atomic_or_32(volatile uint32_t *p, uint32_t i)
00073 {
00074 #if !defined(OF_THREADS)
00075 return (*p |= i);
00076 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00077 return __sync_or_and_fetch(p, i);
00078 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00079 return OSAtomicOr32Barrier(i, p);
00080 #endif
00081 }
00082
00083 static OF_INLINE uint32_t
00084 of_atomic_and_32(volatile uint32_t *p, uint32_t i)
00085 {
00086 #if !defined(OF_THREADS)
00087 return (*p &= i);
00088 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00089 return __sync_and_and_fetch(p, i);
00090 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00091 return OSAtomicAnd32Barrier(i, p);
00092 #endif
00093 }
00094
00095 static OF_INLINE uint32_t
00096 of_atomic_xor_32(volatile uint32_t *p, uint32_t i)
00097 {
00098 #if !defined(OF_THREADS)
00099 return (*p ^= i);
00100 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00101 return __sync_xor_and_fetch(p, i);
00102 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00103 return OSAtomicXor32Barrier(i, p);
00104 #endif
00105 }
00106
00107 static OF_INLINE BOOL
00108 of_atomic_cmpswap_32(volatile int32_t *p, int32_t o, int32_t n)
00109 {
00110 #if !defined(OF_THREADS)
00111 if (*p == o) {
00112 *p = n;
00113 return YES;
00114 }
00115
00116 return NO;
00117 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00118 return __sync_bool_compare_and_swap(p, o, n);
00119 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00120 return OSAtomicCompareAndSwap32Barrier(o, n, p);
00121 #endif
00122 }
00123
00124 static OF_INLINE BOOL
00125 of_atomic_cmpswap_ptr(void* volatile *p, void *o, void *n)
00126 {
00127 #if !defined(OF_THREADS)
00128 if (*p == o) {
00129 *p = n;
00130 return YES;
00131 }
00132
00133 return NO;
00134 #elif defined(OF_HAVE_GCC_ATOMIC_OPS)
00135 return __sync_bool_compare_and_swap(p, o, n);
00136 #elif defined(OF_HAVE_LIBKERN_OSATOMIC_H)
00137 return OSAtomicCompareAndSwapPtrBarrier(o, n, p);
00138 #endif
00139 }