root/src/utils/noit_atomic.h

Revision b4b3415377538d76f5830597b22f2d769c1a6246, 7.4 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

explicit cast to keep warnings down, refs #34

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2005-2009, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *    * Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    * Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *    * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *      of its contributors may be used to endorse or promote products
17  *      derived from this software without specific prior written
18  *      permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #ifndef UTILS_NOIT_ATOMIC_H
34 #define UTILS_NOIT_ATOMIC_H
35
36 #include "noit_config.h"
37
38 typedef int32_t noit_atomic32_t;
39 typedef int64_t noit_atomic64_t;
40
41 #ifdef HAVE_LIBKERN_OSATOMIC_H
42 /*
43  * This secion is for Darwin.
44  * And we simply don't run on 32bit PPC.  Life's a bitch.
45  */
46 #include <libkern/OSAtomic.h>
47 typedef OSSpinLock noit_spinlock_t;
48 #define noit_atomic_cas32(ref,new,old) (OSAtomicCompareAndSwap32(old,new,ref) ? old : new)
49 #define noit_atomic_cas64(ref,new,old) (OSAtomicCompareAndSwap64(old,new,ref) ? old : new)
50 #define noit_atomic_casptr(ref,new,old) (OSAtomicCompareAndSwapPtr(old,new,(void *)ref) ? old : new)
51 #define noit_atomic_add32(ref,diff) OSAtomicAdd32(ref,diff)
52 #define noit_atomic_add64(ref,diff) OSAtomicAdd64(ref,diff)
53 #define noit_atomic_sub32(ref,diff) OSAtomicAdd32(ref,0-(diff))
54 #define noit_atomic_sub64(ref,diff) OSAtomicAdd64(ref,0-(diff))
55 #define noit_atomic_inc32(ref) OSAtomicIncrement32(ref)
56 #define noit_atomic_inc64(ref) OSAtomicIncrement64(ref)
57 #define noit_atomic_dec32(ref) OSAtomicDecrement32(ref)
58 #define noit_atomic_dec64(ref) OSAtomicDecrement64(ref)
59 #define noit_spinlock_lock OSSpinLockLock
60 #define noit_spinlock_unlock OSSpinLockUnlock
61 #define noit_spinlock_trylock OSSpinLockTry
62 #elif defined(__GNUC__)
63
64 #if (SIZEOF_VOID_P == 4)
65 #define noit_atomic_casptr(a,b,c) ((void *)noit_atomic_cas32((vpsized_int *)(a),(vpsized_int)(void *)(b),(vpsized_int)(void *)(c)))
66 #elif (SIZEOF_VOID_P == 8)
67 #define noit_atomic_casptr(a,b,c) ((void *)noit_atomic_cas64((vpsized_int *)(a),(vpsized_int)(void *)(b),(vpsized_int)(void *)(c)))
68 #else
69 #error unsupported pointer width
70 #endif
71
72
73 typedef noit_atomic32_t noit_spinlock_t;
74
75 static inline noit_atomic32_t
76 noit_atomic_cas32(volatile noit_atomic32_t *ptr,
77                   volatile noit_atomic32_t rpl,
78                   volatile noit_atomic32_t curr) {
79   noit_atomic32_t prev;
80   __asm__ volatile (
81       "lock; cmpxchgl %1, %2"
82     : "=a" (prev)
83     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
84     : "memory");
85   return prev;
86 }
87
88 #ifdef __x86_64__
89 static inline noit_atomic64_t
90 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
91                   volatile noit_atomic64_t rpl,
92                   volatile noit_atomic64_t curr) {
93   noit_atomic64_t prev;
94   __asm__ volatile (
95       "lock; cmpxchgq %1, %2"
96     : "=a" (prev)
97     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
98     : "memory");
99   return prev;
100 }
101 #else
102 static inline noit_atomic64_t
103 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
104                   volatile noit_atomic64_t rpl,
105                   volatile noit_atomic64_t curr) {
106   noit_atomic64_t prev;
107   __asm__ volatile (
108       "pushl %%ebx;"
109       "mov 4+%1,%%ecx;"
110       "mov %1,%%ebx;"
111       "lock;"
112       "cmpxchg8b (%3);"
113       "popl %%ebx"
114     : "=A" (prev)
115     : "m" (rpl), "A" (curr), "r" (ptr)
116     : "%ecx", "memory");
117   return prev;
118 };
119 #endif
120
121 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
122   while(noit_atomic_cas32(lock, 1, 0) != 0);
123 }
124 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
125   while(noit_atomic_cas32(lock, 0, 1) != 1);
126 }
127 static inline int noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
128   return (noit_atomic_cas32(lock, 1, 0) == 0);
129 }
130
131 #elif (defined(__amd64) || defined(__i386)) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC))
132
133 typedef noit_atomic32_t noit_spinlock_t;
134
135 extern noit_atomic32_t noit_atomic_cas32(volatile noit_atomic32_t *mem,
136         volatile noit_atomic32_t newval, volatile noit_atomic32_t cmpval);
137 extern noit_atomic64_t noit_atomic_cas64(volatile noit_atomic64_t *mem,
138         volatile noit_atomic64_t newval, volatile noit_atomic64_t cmpval);
139 extern void *noit_atomic_casptr(volatile void **mem,
140         volatile void *newval, volatile void *cmpval);
141
142 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
143   while(noit_atomic_cas32(lock, 1, 0) != 0);
144 }
145 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
146   while(noit_atomic_cas32(lock, 0, 1) != 1);
147 }
148 static inline int noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
149   return (noit_atomic_cas32(lock, 1, 0) == 0);
150 }
151
152 #else
153 #error Please stub out the atomics section for your platform
154 #endif
155
156 #ifndef noit_atomic_add32
157 static inline noit_atomic32_t noit_atomic_add32(volatile noit_atomic32_t *loc,
158                                                 volatile noit_atomic32_t diff) {
159   register noit_atomic32_t current;
160   do {
161     current = *(loc);
162   } while(noit_atomic_cas32(loc, current + diff, current) != current);
163   return current + diff;
164 }
165 #endif
166
167 #ifndef noit_atomic_add64
168 static inline noit_atomic64_t noit_atomic_add64(volatile noit_atomic64_t *loc,
169                                                 volatile noit_atomic64_t diff) {
170   register noit_atomic64_t current;
171   do {
172     current = *(loc);
173   } while(noit_atomic_cas64(loc, current + diff, current) != current);
174   return current + diff;
175 }
176 #endif
177
178 #ifndef noit_atomic_sub32
179 static inline noit_atomic32_t noit_atomic_sub32(volatile noit_atomic32_t *loc,
180                                                 volatile noit_atomic32_t diff) {
181   register noit_atomic32_t current;
182   do {
183     current = *(loc);
184   } while(noit_atomic_cas32(loc, current - diff, current) != current);
185   return current - diff;
186 }
187 #endif
188
189 #ifndef noit_atomic_sub64
190 static inline noit_atomic64_t noit_atomic_sub64(volatile noit_atomic64_t *loc,
191                                                 volatile noit_atomic64_t diff) {
192   register noit_atomic64_t current;
193   do {
194     current = *(loc);
195   } while(noit_atomic_cas64(loc, current - diff, current) != current);
196   return current - diff;
197 }
198 #endif
199
200 #ifndef noit_atomic_inc32
201 #define noit_atomic_inc32(a) noit_atomic_add32(a, 1)
202 #endif
203
204 #ifndef noit_atomic_inc64
205 #define noit_atomic_inc64(a) noit_atomic_add64(a, 1)
206 #endif
207
208 #ifndef noit_atomic_dec32
209 #define noit_atomic_dec32(a) noit_atomic_add32(a, -1)
210 #endif
211
212 #ifndef noit_atomic_dec64
213 #define noit_atomic_dec64(a) noit_atomic_add64(a, -1)
214 #endif
215
216 #endif
Note: See TracBrowser for help on using the browser.