4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009 by Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
32 * All operations are implemented by serializing them through a global
33 * pthread mutex. This provides a correct generic implementation.
34 * However all supported architectures are encouraged to provide a
35 * native implementation is assembly for performance reasons.
37 pthread_mutex_t atomic_lock
= PTHREAD_MUTEX_INITIALIZER
;
40 * Theses are the void returning variants
43 #define ATOMIC_INC(name, type) \
44 void atomic_inc_##name(volatile type *target) \
46 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
48 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
51 ATOMIC_INC(long, unsigned long)
52 ATOMIC_INC(8, uint8_t)
53 ATOMIC_INC(uchar
, uchar_t
)
54 ATOMIC_INC(16, uint16_t)
55 ATOMIC_INC(ushort
, ushort_t
)
56 ATOMIC_INC(32, uint32_t)
57 ATOMIC_INC(uint
, uint_t
)
58 ATOMIC_INC(ulong
, ulong_t
)
59 ATOMIC_INC(64, uint64_t)
62 #define ATOMIC_DEC(name, type) \
63 void atomic_dec_##name(volatile type *target) \
65 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
67 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
70 ATOMIC_DEC(long, unsigned long)
71 ATOMIC_DEC(8, uint8_t)
72 ATOMIC_DEC(uchar
, uchar_t
)
73 ATOMIC_DEC(16, uint16_t)
74 ATOMIC_DEC(ushort
, ushort_t
)
75 ATOMIC_DEC(32, uint32_t)
76 ATOMIC_DEC(uint
, uint_t
)
77 ATOMIC_DEC(ulong
, ulong_t
)
78 ATOMIC_DEC(64, uint64_t)
81 #define ATOMIC_ADD(name, type1, type2) \
82 void atomic_add_##name(volatile type1 *target, type2 bits) \
84 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
86 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
89 ATOMIC_ADD(8, uint8_t, int8_t)
90 ATOMIC_ADD(char, uchar_t
, signed char)
91 ATOMIC_ADD(16, uint16_t, int16_t)
92 ATOMIC_ADD(short, ushort_t
, short)
93 ATOMIC_ADD(32, uint32_t, int32_t)
94 ATOMIC_ADD(int, uint_t
, int)
95 ATOMIC_ADD(long, ulong_t
, long)
96 ATOMIC_ADD(64, uint64_t, int64_t)
99 atomic_add_ptr(volatile void *target
, ssize_t bits
)
101 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
102 *(caddr_t
*)target
+= bits
;
103 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
107 #define ATOMIC_SUB(name, type1, type2) \
108 void atomic_sub_##name(volatile type1 *target, type2 bits) \
110 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
112 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
115 ATOMIC_SUB(8, uint8_t, int8_t)
116 ATOMIC_SUB(char, uchar_t
, signed char)
117 ATOMIC_SUB(16, uint16_t, int16_t)
118 ATOMIC_SUB(short, ushort_t
, short)
119 ATOMIC_SUB(32, uint32_t, int32_t)
120 ATOMIC_SUB(int, uint_t
, int)
121 ATOMIC_SUB(long, ulong_t
, long)
122 ATOMIC_SUB(64, uint64_t, int64_t)
125 atomic_sub_ptr(volatile void *target
, ssize_t bits
)
127 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
128 *(caddr_t
*)target
-= bits
;
129 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
133 #define ATOMIC_OR(name, type) \
134 void atomic_or_##name(volatile type *target, type bits) \
136 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
138 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
141 ATOMIC_OR(8, uint8_t)
142 ATOMIC_OR(uchar
, uchar_t
)
143 ATOMIC_OR(16, uint16_t)
144 ATOMIC_OR(ushort
, ushort_t
)
145 ATOMIC_OR(32, uint32_t)
146 ATOMIC_OR(uint
, uint_t
)
147 ATOMIC_OR(ulong
, ulong_t
)
148 ATOMIC_OR(64, uint64_t)
151 #define ATOMIC_AND(name, type) \
152 void atomic_and_##name(volatile type *target, type bits) \
154 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
156 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
159 ATOMIC_AND(8, uint8_t)
160 ATOMIC_AND(uchar
, uchar_t
)
161 ATOMIC_AND(16, uint16_t)
162 ATOMIC_AND(ushort
, ushort_t
)
163 ATOMIC_AND(32, uint32_t)
164 ATOMIC_AND(uint
, uint_t
)
165 ATOMIC_AND(ulong
, ulong_t
)
166 ATOMIC_AND(64, uint64_t)
170 * New value returning variants
173 #define ATOMIC_INC_NV(name, type) \
174 type atomic_inc_##name##_nv(volatile type *target) \
177 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
178 rc = (++(*target)); \
179 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
183 ATOMIC_INC_NV(long, unsigned long)
184 ATOMIC_INC_NV(8, uint8_t)
185 ATOMIC_INC_NV(uchar
, uchar_t
)
186 ATOMIC_INC_NV(16, uint16_t)
187 ATOMIC_INC_NV(ushort
, ushort_t
)
188 ATOMIC_INC_NV(32, uint32_t)
189 ATOMIC_INC_NV(uint
, uint_t
)
190 ATOMIC_INC_NV(ulong
, ulong_t
)
191 ATOMIC_INC_NV(64, uint64_t)
194 #define ATOMIC_DEC_NV(name, type) \
195 type atomic_dec_##name##_nv(volatile type *target) \
198 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
199 rc = (--(*target)); \
200 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
204 ATOMIC_DEC_NV(long, unsigned long)
205 ATOMIC_DEC_NV(8, uint8_t)
206 ATOMIC_DEC_NV(uchar
, uchar_t
)
207 ATOMIC_DEC_NV(16, uint16_t)
208 ATOMIC_DEC_NV(ushort
, ushort_t
)
209 ATOMIC_DEC_NV(32, uint32_t)
210 ATOMIC_DEC_NV(uint
, uint_t
)
211 ATOMIC_DEC_NV(ulong
, ulong_t
)
212 ATOMIC_DEC_NV(64, uint64_t)
215 #define ATOMIC_ADD_NV(name, type1, type2) \
216 type1 atomic_add_##name##_nv(volatile type1 *target, type2 bits)\
219 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
220 rc = (*target += bits); \
221 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
225 ATOMIC_ADD_NV(8, uint8_t, int8_t)
226 ATOMIC_ADD_NV(char, uchar_t
, signed char)
227 ATOMIC_ADD_NV(16, uint16_t, int16_t)
228 ATOMIC_ADD_NV(short, ushort_t
, short)
229 ATOMIC_ADD_NV(32, uint32_t, int32_t)
230 ATOMIC_ADD_NV(int, uint_t
, int)
231 ATOMIC_ADD_NV(long, ulong_t
, long)
232 ATOMIC_ADD_NV(64, uint64_t, int64_t)
235 atomic_add_ptr_nv(volatile void *target
, ssize_t bits
)
239 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
240 ptr
= (*(caddr_t
*)target
+= bits
);
241 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
247 #define ATOMIC_SUB_NV(name, type1, type2) \
248 type1 atomic_sub_##name##_nv(volatile type1 *target, type2 bits)\
251 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
252 rc = (*target -= bits); \
253 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
257 ATOMIC_SUB_NV(8, uint8_t, int8_t)
258 ATOMIC_SUB_NV(char, uchar_t
, signed char)
259 ATOMIC_SUB_NV(16, uint16_t, int16_t)
260 ATOMIC_SUB_NV(short, ushort_t
, short)
261 ATOMIC_SUB_NV(32, uint32_t, int32_t)
262 ATOMIC_SUB_NV(int, uint_t
, int)
263 ATOMIC_SUB_NV(long, ulong_t
, long)
264 ATOMIC_SUB_NV(64, uint64_t, int64_t)
267 atomic_sub_ptr_nv(volatile void *target
, ssize_t bits
)
271 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
272 ptr
= (*(caddr_t
*)target
-= bits
);
273 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
279 #define ATOMIC_OR_NV(name, type) \
280 type atomic_or_##name##_nv(volatile type *target, type bits) \
283 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
284 rc = (*target |= bits); \
285 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
289 ATOMIC_OR_NV(long, unsigned long)
290 ATOMIC_OR_NV(8, uint8_t)
291 ATOMIC_OR_NV(uchar
, uchar_t
)
292 ATOMIC_OR_NV(16, uint16_t)
293 ATOMIC_OR_NV(ushort
, ushort_t
)
294 ATOMIC_OR_NV(32, uint32_t)
295 ATOMIC_OR_NV(uint
, uint_t
)
296 ATOMIC_OR_NV(ulong
, ulong_t
)
297 ATOMIC_OR_NV(64, uint64_t)
300 #define ATOMIC_AND_NV(name, type) \
301 type atomic_and_##name##_nv(volatile type *target, type bits) \
304 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
305 rc = (*target &= bits); \
306 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
310 ATOMIC_AND_NV(long, unsigned long)
311 ATOMIC_AND_NV(8, uint8_t)
312 ATOMIC_AND_NV(uchar
, uchar_t
)
313 ATOMIC_AND_NV(16, uint16_t)
314 ATOMIC_AND_NV(ushort
, ushort_t
)
315 ATOMIC_AND_NV(32, uint32_t)
316 ATOMIC_AND_NV(uint
, uint_t
)
317 ATOMIC_AND_NV(ulong
, ulong_t
)
318 ATOMIC_AND_NV(64, uint64_t)
322 * If *arg1 == arg2, set *arg1 = arg3; return old value
325 #define ATOMIC_CAS(name, type) \
326 type atomic_cas_##name(volatile type *target, type arg1, type arg2) \
329 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
333 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
337 ATOMIC_CAS(8, uint8_t)
338 ATOMIC_CAS(uchar
, uchar_t
)
339 ATOMIC_CAS(16, uint16_t)
340 ATOMIC_CAS(ushort
, ushort_t
)
341 ATOMIC_CAS(32, uint32_t)
342 ATOMIC_CAS(uint
, uint_t
)
343 ATOMIC_CAS(ulong
, ulong_t
)
344 ATOMIC_CAS(64, uint64_t)
347 atomic_cas_ptr(volatile void *target
, void *arg1
, void *arg2
)
351 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
352 old
= *(void **)target
;
354 *(void **)target
= arg2
;
355 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
362 * Swap target and return old value
365 #define ATOMIC_SWAP(name, type) \
366 type atomic_swap_##name(volatile type *target, type bits) \
369 VERIFY3S(pthread_mutex_lock(&atomic_lock), ==, 0); \
372 VERIFY3S(pthread_mutex_unlock(&atomic_lock), ==, 0); \
376 ATOMIC_SWAP(8, uint8_t)
377 ATOMIC_SWAP(uchar
, uchar_t
)
378 ATOMIC_SWAP(16, uint16_t)
379 ATOMIC_SWAP(ushort
, ushort_t
)
380 ATOMIC_SWAP(32, uint32_t)
381 ATOMIC_SWAP(uint
, uint_t
)
382 ATOMIC_SWAP(ulong
, ulong_t
)
383 ATOMIC_SWAP(64, uint64_t)
386 atomic_swap_ptr(volatile void *target
, void *bits
)
390 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
391 old
= *(void **)target
;
392 *(void **)target
= bits
;
393 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
400 atomic_set_long_excl(volatile ulong_t
*target
, uint_t value
)
404 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
405 bit
= (1UL << value
);
406 if ((*target
& bit
) != 0) {
407 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
411 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
417 atomic_clear_long_excl(volatile ulong_t
*target
, uint_t value
)
421 VERIFY3S(pthread_mutex_lock(&atomic_lock
), ==, 0);
422 bit
= (1UL << value
);
423 if ((*target
& bit
) != 0) {
424 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
428 VERIFY3S(pthread_mutex_unlock(&atomic_lock
), ==, 0);
436 /* XXX - Implement me */
442 /* XXX - Implement me */
446 membar_producer(void)
448 /* XXX - Implement me */
452 membar_consumer(void)
454 /* XXX - Implement me */
457 /* Legacy kernel interfaces; they will go away (eventually). */
460 cas8(uint8_t *target
, uint8_t arg1
, uint8_t arg2
)
462 return (atomic_cas_8(target
, arg1
, arg2
));
466 cas32(uint32_t *target
, uint32_t arg1
, uint32_t arg2
)
468 return (atomic_cas_32(target
, arg1
, arg2
));
472 cas64(uint64_t *target
, uint64_t arg1
, uint64_t arg2
)
474 return (atomic_cas_64(target
, arg1
, arg2
));
478 caslong(ulong_t
*target
, ulong_t arg1
, ulong_t arg2
)
480 return (atomic_cas_ulong(target
, arg1
, arg2
));
484 casptr(void *target
, void *arg1
, void *arg2
)
486 return (atomic_cas_ptr(target
, arg1
, arg2
));
490 atomic_and_long(ulong_t
*target
, ulong_t bits
)
492 return (atomic_and_ulong(target
, bits
));
496 atomic_or_long(ulong_t
*target
, ulong_t bits
)
498 return (atomic_or_ulong(target
, bits
));