root/src/utils/noit_atomic.h

Revision 6fcedd04445d35373bec21b015cbd0e863fe6c9c, 7.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 years ago)

support sparc like we mean it

  • 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 #if defined(__GNUC__)
42
43 typedef noit_atomic32_t noit_spinlock_t;
44 static inline noit_atomic32_t
45 noit_atomic_cas32(volatile noit_atomic32_t *ptr,
46                   volatile noit_atomic32_t rpl,
47                   volatile noit_atomic32_t curr) {
48   noit_atomic32_t prev;
49   __asm__ volatile (
50       "lock; cmpxchgl %1, %2"
51     : "=a" (prev)
52     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
53     : "memory");
54   return prev;
55 }
56
57 #if (SIZEOF_VOID_P == 4)
58 static inline void *
59 noit_atomic_casptr(volatile void **ptr,
60                    volatile void *rpl,
61                    volatile void *curr) {
62   void *prev;
63   __asm__ volatile (
64       "lock; cmpxchgl %1, %2"
65     : "=a" (prev)
66     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
67     : "memory");
68   return prev;
69 }
70 #endif
71
72 #ifdef __x86_64__
73 static inline noit_atomic64_t
74 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
75                   volatile noit_atomic64_t rpl,
76                   volatile noit_atomic64_t curr) {
77   noit_atomic64_t prev;
78   __asm__ volatile (
79       "lock; cmpxchgq %1, %2"
80     : "=a" (prev)
81     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
82     : "memory");
83   return prev;
84 }
85 #if (SIZEOF_VOID_P == 8)
86 static inline void *
87 noit_atomic_casptr(volatile void **ptr,
88                   volatile void *rpl,
89                   volatile void *curr) {
90   void *prev;
91   __asm__ volatile (
92       "lock; cmpxchgq %1, %2"
93     : "=a" (prev)
94     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
95     : "memory");
96   return prev;
97 }
98 #endif
99 #else
100 static inline noit_atomic64_t
101 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
102                   volatile noit_atomic64_t rpl,
103                   volatile noit_atomic64_t curr) {
104   noit_atomic64_t prev;
105 #ifdef __PIC__
106   __asm__ volatile (
107       "pushl %%ebx;"
108       "mov 4+%1,%%ecx;"
109       "mov %1,%%ebx;"
110       "lock;"
111       "cmpxchg8b (%3);"
112       "popl %%ebx"
113     : "=A" (prev)
114     : "m" (rpl), "A" (curr), "r" (ptr)
115     : "%ecx", "memory", "cc");
116 #else
117   __asm__ volatile (
118       "lock;"
119       "cmpxchg8b (%3);"
120     : "=A" (prev)
121     : "m" (rpl), "A" (curr), "r" (ptr)
122     : "memory", "cc");
123 #endif
124   return prev;
125 };
126 #if (SIZEOF_VOID_P == 8)
127 /* This should never be triggered.. 8 byte pointers on 32bit machines */
128 #error "64bit pointers on a 32bit architecture?"
129 #endif
130 #endif
131
132 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
133   while(noit_atomic_cas32(lock, 1, 0) != 0);
134 }
135 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
136   while(noit_atomic_cas32(lock, 0, 1) != 1);
137 }
138 static inline int noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
139   return (noit_atomic_cas32(lock, 1, 0) == 0);
140 }
141
142 #elif (defined(__sparc) || defined(__sparcv9) || defined(__amd64) || defined(__i386)) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC))
143
144 typedef noit_atomic32_t noit_spinlock_t;
145
146 extern noit_atomic32_t noit_atomic_cas32(volatile noit_atomic32_t *mem,
147         volatile noit_atomic32_t newval, volatile noit_atomic32_t cmpval);
148 extern noit_atomic64_t noit_atomic_cas64(volatile noit_atomic64_t *mem,
149         volatile noit_atomic64_t newval, volatile noit_atomic64_t cmpval);
150 extern void *noit_atomic_casptr(volatile void **mem,
151         volatile void *newval, volatile void *cmpval);
152
153 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
154   while(noit_atomic_cas32(lock, 1, 0) != 0);
155 }
156 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
157   while(noit_atomic_cas32(lock, 0, 1) != 1);
158 }
159 static inline int noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
160   return (noit_atomic_cas32(lock, 1, 0) == 0);
161 }
162
163 #else
164 #error Please stub out the atomics section for your platform
165 #endif
166
167 #ifndef noit_atomic_add32
168 static inline noit_atomic32_t noit_atomic_add32(volatile noit_atomic32_t *loc,
169                                                 volatile noit_atomic32_t diff) {
170   register noit_atomic32_t current;
171   do {
172     current = *(loc);
173   } while(noit_atomic_cas32(loc, current + diff, current) != current);
174   return current + diff;
175 }
176 #endif
177
178 #ifndef noit_atomic_add64
179 static inline noit_atomic64_t noit_atomic_add64(volatile noit_atomic64_t *loc,
180                                                 volatile noit_atomic64_t diff) {
181   register noit_atomic64_t current;
182   do {
183     current = *(loc);
184   } while(noit_atomic_cas64(loc, current + diff, current) != current);
185   return current + diff;
186 }
187 #endif
188
189 #ifndef noit_atomic_sub32
190 static inline noit_atomic32_t noit_atomic_sub32(volatile noit_atomic32_t *loc,
191                                                 volatile noit_atomic32_t diff) {
192   register noit_atomic32_t current;
193   do {
194     current = *(loc);
195   } while(noit_atomic_cas32(loc, current - diff, current) != current);
196   return current - diff;
197 }
198 #endif
199
200 #ifndef noit_atomic_sub64
201 static inline noit_atomic64_t noit_atomic_sub64(volatile noit_atomic64_t *loc,
202                                                 volatile noit_atomic64_t diff) {
203   register noit_atomic64_t current;
204   do {
205     current = *(loc);
206   } while(noit_atomic_cas64(loc, current - diff, current) != current);
207   return current - diff;
208 }
209 #endif
210
211 #ifndef noit_atomic_inc32
212 #define noit_atomic_inc32(a) noit_atomic_add32(a, 1)
213 #endif
214
215 #ifndef noit_atomic_inc64
216 #define noit_atomic_inc64(a) noit_atomic_add64(a, 1)
217 #endif
218
219 #ifndef noit_atomic_dec32
220 #define noit_atomic_dec32(a) noit_atomic_add32(a, -1)
221 #endif
222
223 #ifndef noit_atomic_dec64
224 #define noit_atomic_dec64(a) noit_atomic_add64(a, -1)
225 #endif
226
227 #endif
Note: See TracBrowser for help on using the browser.