root/src/utils/noit_atomic.h

Revision 1a95a959128497a0d191d00dac203df351fdcac8, 5.6 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 10 years ago)

closes #46

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #ifndef UTILS_NOIT_ATOMIC_H
7 #define UTILS_NOIT_ATOMIC_H
8
9 #include "noit_config.h"
10
11 typedef int32_t noit_atomic32_t;
12 typedef int64_t noit_atomic64_t;
13
14 #ifdef HAVE_LIBKERN_OSATOMIC_H
15 /*
16  * This secion is for Darwin.
17  * And we simply don't run on 32bit PPC.  Life's a bitch.
18  */
19 #include <libkern/OSAtomic.h>
20 typedef OSSpinLock noit_spinlock_t;
21 #define noit_atomic_cas32(ref,new,old) (OSAtomicCompareAndSwap32(old,new,ref) ? old : new)
22 #define noit_atomic_cas64(ref,new,old) (OSAtomicCompareAndSwap64(old,new,ref) ? old : new)
23 #define noit_atomic_add32(ref,diff) OSAtomicAdd32(ref,diff)
24 #define noit_atomic_add64(ref,diff) OSAtomicAdd64(ref,diff)
25 #define noit_atomic_sub32(ref,diff) OSAtomicAdd32(ref,0-(diff))
26 #define noit_atomic_sub64(ref,diff) OSAtomicAdd64(ref,0-(diff))
27 #define noit_atomic_inc32(ref) OSAtomicIncrement32(ref)
28 #define noit_atomic_inc64(ref) OSAtomicIncrement64(ref)
29 #define noit_atomic_dec32(ref) OSAtomicDecrement32(ref)
30 #define noit_atomic_dec64(ref) OSAtomicDecrement64(ref)
31 #define noit_spinlock_lock OSSpinLockLock
32 #define noit_spinlock_unlock OSSpinLockUnlock
33 #define noit_spinlock_trylock OSSpinLockTry
34 #elif defined(__GNUC__)
35
36 #if (SIZEOF_VOID_P == 4)
37 #define noit_atomic_casptr(a,b,c) noit_atomic_cas32((a),(void *)(b),(void *)(c))
38 #elif (SIZEOF_VOID_P == 8)
39 #define noit_atomic_casptr(a,b,c) noit_atomic_cas64((a),(void *)(b),(void *)(c))
40 #else
41 #error unsupported pointer width
42 #endif
43
44
45 typedef noit_atomic32_t noit_spinlock_t;
46
47 static inline noit_atomic32_t
48 noit_atomic_cas32(volatile noit_atomic32_t *ptr,
49                   volatile noit_atomic32_t rpl,
50                   volatile noit_atomic32_t curr) {
51   noit_atomic32_t prev;
52   __asm__ volatile (
53       "lock; cmpxchgl %1, %2"
54     : "=a" (prev)
55     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
56     : "memory");
57   return prev;
58 }
59
60 #ifdef __x86_64__
61 static inline noit_atomic64_t
62 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
63                   volatile noit_atomic64_t rpl,
64                   volatile noit_atomic64_t curr) {
65   noit_atomic64_t prev;
66   __asm__ volatile (
67       "lock; cmpxchgq %1, %2"
68     : "=a" (prev)
69     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
70     : "memory");
71   return prev;
72 }
73 #else
74 static inline noit_atomic64_t
75 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
76                   volatile noit_atomic64_t rpl,
77                   volatile noit_atomic64_t curr) {
78   noit_atomic64_t prev;
79   __asm__ volatile (
80       "pushl %%ebx;"
81       "mov 4+%1,%%ecx;"
82       "mov %1,%%ebx;"
83       "lock;"
84       "cmpxchg8b (%3);"
85       "popl %%ebx"
86     : "=A" (prev)
87     : "m" (rpl), "A" (curr), "r" (ptr)
88     : "%ebx", "%ecx", "memory");
89   return prev;
90 };
91 #endif
92
93 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
94   while(noit_atomic_cas32(lock, 1, 0) != 0);
95 }
96 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
97   while(noit_atomic_cas32(lock, 0, 1) != 1);
98 }
99 static inline int noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
100   return (noit_atomic_cas32(lock, 1, 0) == 0);
101 }
102
103 #elif (defined(__amd64) || defined(__i386)) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC))
104
105 typedef noit_atomic32_t noit_spinlock_t;
106
107 extern noit_atomic32_t noit_atomic_cas32(volatile noit_atomic32_t *mem,
108         volatile noit_atomic32_t newval, volatile noit_atomic32_t cmpval);
109 extern noit_atomic64_t noit_atomic_cas64(volatile noit_atomic64_t *mem,
110         volatile noit_atomic64_t newval, volatile noit_atomic64_t cmpval);
111
112 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
113   while(noit_atomic_cas32(lock, 1, 0) != 0);
114 }
115 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
116   while(noit_atomic_cas32(lock, 0, 1) != 1);
117 }
118 static inline int noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
119   return (noit_atomic_cas32(lock, 1, 0) == 0);
120 }
121
122 #else
123 #error Please stub out the atomics section for your platform
124 #endif
125
126 #ifndef noit_atomic_add32
127 static inline noit_atomic32_t noit_atomic_add32(volatile noit_atomic32_t *loc,
128                                                 volatile noit_atomic32_t diff) {
129   register noit_atomic32_t current;
130   do {
131     current = *(loc);
132   } while(noit_atomic_cas32(loc, current + diff, current) != current);
133   return current + diff;
134 }
135 #endif
136
137 #ifndef noit_atomic_add64
138 static inline noit_atomic64_t noit_atomic_add64(volatile noit_atomic64_t *loc,
139                                                 volatile noit_atomic64_t diff) {
140   register noit_atomic64_t current;
141   do {
142     current = *(loc);
143   } while(noit_atomic_cas64(loc, current + diff, current) != current);
144   return current + diff;
145 }
146 #endif
147
148 #ifndef noit_atomic_sub32
149 static inline noit_atomic32_t noit_atomic_sub32(volatile noit_atomic32_t *loc,
150                                                 volatile noit_atomic32_t diff) {
151   register noit_atomic32_t current;
152   do {
153     current = *(loc);
154   } while(noit_atomic_cas32(loc, current - diff, current) != current);
155   return current - diff;
156 }
157 #endif
158
159 #ifndef noit_atomic_sub64
160 static inline noit_atomic64_t noit_atomic_sub64(volatile noit_atomic64_t *loc,
161                                                 volatile noit_atomic64_t diff) {
162   register noit_atomic64_t current;
163   do {
164     current = *(loc);
165   } while(noit_atomic_cas64(loc, current - diff, current) != current);
166   return current - diff;
167 }
168 #endif
169
170 #ifndef noit_atomic_inc32
171 #define noit_atomic_inc32(a) noit_atomic_add32(a, 1)
172 #endif
173
174 #ifndef noit_atomic_inc64
175 #define noit_atomic_inc64(a) noit_atomic_add64(a, 1)
176 #endif
177
178 #ifndef noit_atomic_dec32
179 #define noit_atomic_dec32(a) noit_atomic_add32(a, -1)
180 #endif
181
182 #ifndef noit_atomic_dec64
183 #define noit_atomic_dec64(a) noit_atomic_add64(a, -1)
184 #endif
185
186 #endif
Note: See TracBrowser for help on using the browser.