root/src/utils/noit_atomic.h

Revision cd3d910e5e82174794737b8bdbe2d55a729fda84, 6.5 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 8 years ago)

this should be better, refs #305

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