2 * Copyright (c) 2010 Your Filesystem Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 #ifndef OPENAFS_RX_ATOMIC_H
26 #define OPENAFS_RX_ATOMIC_H 1
28 #define RX_ATOMIC_INIT(i) { (i) }
36 rx_atomic_set(rx_atomic_t *atomic, int val) {
41 rx_atomic_read(rx_atomic_t *atomic) {
46 rx_atomic_inc(rx_atomic_t *atomic) {
47 InterlockedIncrement(&atomic->var);
51 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
52 return InterlockedIncrement(&atomic->var);
56 rx_atomic_add(rx_atomic_t *atomic, int change) {
57 InterlockedExchangeAdd(&atomic->var, change);
61 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
62 return InterlockedExchangeAdd(&atomic->var, change) + change;
66 rx_atomic_dec(rx_atomic_t *atomic) {
67 InterlockedDecrement(&atomic->var);
71 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
72 return InterlockedDecrement(&atomic->var);
76 rx_atomic_sub(rx_atomic_t *atomic, int change) {
77 InterlockedExchangeAdd(&atomic->var, 0 - change);
81 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
82 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
85 /* No InterlockedOr or InterlockedAnd on ix86, so just use the
86 * BitTest functions */
89 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
90 (void) InterlockedBitTestAndSet(&atomic->var, bit);
94 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
95 (void) InterlockedBitTestAndReset(&atomic->var, bit);
99 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
100 return InterlockedBitTestAndSet(&atomic->var, bit);
104 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
105 return InterlockedBitTestAndReset(&atomic->var, bit);
108 #elif defined(AFS_AIX61_ENV) || defined(AFS_USR_AIX61_ENV)
109 #include <sys/atomic_op.h>
116 rx_atomic_set(rx_atomic_t *atomic, int val) {
121 rx_atomic_read(rx_atomic_t *atomic) {
126 rx_atomic_inc(rx_atomic_t *atomic) {
127 fetch_and_add(&atomic->var, 1);
131 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
132 return (fetch_and_add(&atomic->var, 1) + 1);
136 rx_atomic_add(rx_atomic_t *atomic, int change) {
137 fetch_and_add(&atomic->var, change);
141 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
142 return (fetch_and_add(&atomic->var, change) + change);
146 rx_atomic_dec(rx_atomic_t *atomic) {
147 fetch_and_add(&atomic->var, -1);
151 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
152 return (fetch_and_add(&atomic->var, -1) - 1);
156 rx_atomic_sub(rx_atomic_t *atomic, int change) {
157 fetch_and_add(&atomic->var, -change);
161 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
162 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
166 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
167 fetch_and_or(&atomic->var, 1<<bit);
171 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
172 fetch_and_and(&atomic->var, ~(1<<bit));
176 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
177 return (fetch_and_or(&atomic->var, (1<<bit)) & 1<<bit) != 0;
181 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
182 return (fetch_and_and(&atomic->var, ~(1<<bit)) & 1<<bit) != 0;
185 #elif defined(AFS_DARWIN80_ENV) || defined(AFS_USR_DARWIN80_ENV)
187 #include <libkern/OSAtomic.h>
188 #if defined(KERNEL) && !defined(UKERNEL)
189 #define OSAtomicIncrement32 OSIncrementAtomic
190 #define OSAtomicAdd32 OSAddAtomic
191 #define OSAtomicDecrement32 OSDecrementAtomic
192 #define OSAtomicOr32 OSBitOrAtomic
193 #define OSAtomicAnd32 OSBitAndAtomic
201 rx_atomic_set(rx_atomic_t *atomic, int val) {
206 rx_atomic_read(rx_atomic_t *atomic) {
211 rx_atomic_inc(rx_atomic_t *atomic) {
212 OSAtomicIncrement32(&atomic->var);
216 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
217 return OSAtomicIncrement32(&atomic->var);
221 rx_atomic_add(rx_atomic_t *atomic, int change) {
222 OSAtomicAdd32(change, &atomic->var);
226 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
227 return OSAtomicAdd32(change, &atomic->var);
231 rx_atomic_dec(rx_atomic_t *atomic) {
232 OSAtomicDecrement32(&atomic->var);
236 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
237 return OSAtomicDecrement32(&atomic->var);
241 rx_atomic_sub(rx_atomic_t *atomic, int change) {
242 OSAtomicAdd32(0 - change, &atomic->var);
246 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
247 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
251 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
252 OSAtomicOr32(1<<bit, (volatile uint32_t *)&atomic->var);
256 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
257 OSAtomicAnd32(~(1<<bit), (volatile uint32_t *)&atomic->var);
261 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
262 return ((OSAtomicOr32Orig(1<<bit, (volatile uint32_t *)&atomic->var) & 1<<bit)
267 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
268 return ((OSAtomicAnd32Orig(~(1<<bit),
269 (volatile uint32_t *)&atomic->var) & 1<<bit)
273 #elif defined(AFS_LINUX26_ENV) && defined(KERNEL)
274 #include <asm/atomic.h>
276 typedef atomic_t rx_atomic_t;
278 #define rx_atomic_set(X, V) atomic_set(X, V)
279 #define rx_atomic_read(X) atomic_read(X)
280 #define rx_atomic_inc(X) atomic_inc(X)
281 #define rx_atomic_inc_and_read(X) atomic_inc_return(X)
282 #define rx_atomic_add(X, V) atomic_add(V, X)
283 #define rx_atomic_add_and_read(X, V) atomic_add_return(V, X);
284 #define rx_atomic_dec(X) atomic_dec(X)
285 #define rx_atomic_dec_and_read(X) atomic_dec_return(X)
286 #define rx_atomic_sub(X, V) atomic_sub(V, X)
287 #define rx_atomic_test_bit(X, B) test_bit(B, (unsigned long *) &(X)->counter)
288 #define rx_atomic_set_bit(X, B) set_bit(B, (unsigned long *) &(X)->counter)
289 #define rx_atomic_clear_bit(X, B) clear_bit(B, (unsigned long *) &(X)->counter)
290 #define rx_atomic_test_and_set_bit(X, B) test_and_set_bit(B, (unsigned long *) &(X)->counter)
291 #define rx_atomic_test_and_clear_bit(X, B) test_and_clear_bit(B, (unsigned long *) &(X)->counter)
293 #elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL))
295 # if defined(KERNEL) && !defined(UKERNEL)
296 # include <sys/atomic.h>
301 #ifndef AFS_SUN510_ENV
302 # define atomic_inc_32(X) atomic_add_32((X), 1)
303 # define atomic_inc_32_nv(X) atomic_add_32_nv((X), 1)
304 # define atomic_dec_32(X) atomic_add_32((X), -1)
305 # define atomic_dec_32_nv(X) atomic_add_32_nv((X), -1)
309 volatile unsigned int var;
313 rx_atomic_set(rx_atomic_t *atomic, int val) {
318 rx_atomic_read(rx_atomic_t *atomic) {
323 rx_atomic_inc(rx_atomic_t *atomic) {
324 atomic_inc_32(&atomic->var);
328 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
329 return atomic_inc_32_nv(&atomic->var);
333 rx_atomic_add(rx_atomic_t *atomic, int change) {
334 atomic_add_32(&atomic->var, change);
338 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
339 return atomic_add_32_nv(&atomic->var, change);
343 rx_atomic_dec(rx_atomic_t *atomic) {
344 atomic_dec_32(&atomic->var);
348 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
349 return atomic_dec_32_nv(&atomic->var);
353 rx_atomic_sub(rx_atomic_t *atomic, int change) {
354 atomic_add_32(&atomic->var, 0 - change);
358 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
359 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
363 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
364 atomic_or_32(&atomic->var, 1<<bit);
368 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
369 atomic_and_32(&atomic->var, ~(1<<bit));
373 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
374 return (atomic_set_long_excl(&atomic->var, bit) == -1);
378 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
379 return (atomic_clear_long_excl(&atomic->var, bit) == 0);
382 #elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD)
389 rx_atomic_set(rx_atomic_t *atomic, int val) {
394 rx_atomic_read(rx_atomic_t *atomic) {
399 rx_atomic_inc(rx_atomic_t *atomic) {
400 (void)__sync_fetch_and_add(&atomic->var, 1);
404 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
405 return __sync_add_and_fetch(&atomic->var, 1);
409 rx_atomic_add(rx_atomic_t *atomic, int change) {
410 (void)__sync_fetch_and_add(&atomic->var, change);
414 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
415 return __sync_fetch_and_add(&atomic->var, change);
419 rx_atomic_dec(rx_atomic_t *atomic) {
420 (void)__sync_fetch_and_sub(&atomic->var, 1);
424 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
425 return __sync_sub_and_fetch(&atomic->var, 1);
429 rx_atomic_sub(rx_atomic_t *atomic, int change) {
430 (void)__sync_fetch_and_sub(&atomic->var, change);
434 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
435 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
439 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
440 (void)__sync_fetch_and_or(&atomic->var, 1<<bit);
444 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
445 (void)__sync_fetch_and_and(&atomic->var, ~(1<<bit));
449 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
450 return (__sync_fetch_and_or(&atomic->var, 1<<bit) & 1<<bit) != 0;
454 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
455 return (__sync_fetch_and_and(&atomic->var, ~(1<<bit)) & 1<<bit) != 0;
460 /* If we're on a platform where we have no idea how to do atomics,
461 * then we fall back to using a single process wide mutex to protect
462 * all atomic variables. This won't be the quickest thing ever.
465 #ifdef RX_ENABLE_LOCKS
466 extern afs_kmutex_t rx_atomic_mutex;
474 rx_atomic_set(rx_atomic_t *atomic, int val) {
475 MUTEX_ENTER(&rx_atomic_mutex);
477 MUTEX_EXIT(&rx_atomic_mutex);
481 rx_atomic_read(rx_atomic_t *atomic) {
484 MUTEX_ENTER(&rx_atomic_mutex);
486 MUTEX_EXIT(&rx_atomic_mutex);
492 rx_atomic_inc(rx_atomic_t *atomic) {
493 MUTEX_ENTER(&rx_atomic_mutex);
495 MUTEX_EXIT(&rx_atomic_mutex);
499 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
501 MUTEX_ENTER(&rx_atomic_mutex);
503 retval = atomic->var;
504 MUTEX_EXIT(&rx_atomic_mutex);
509 rx_atomic_add(rx_atomic_t *atomic, int change) {
510 MUTEX_ENTER(&rx_atomic_mutex);
511 atomic->var += change;
512 MUTEX_EXIT(&rx_atomic_mutex);
516 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
519 MUTEX_ENTER(&rx_atomic_mutex);
520 atomic->var += change;
521 retval = atomic->var;
522 MUTEX_EXIT(&rx_atomic_mutex);
528 rx_atomic_dec(rx_atomic_t *atomic) {
529 MUTEX_ENTER(&rx_atomic_mutex);
531 MUTEX_EXIT(&rx_atomic_mutex);
535 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
537 MUTEX_ENTER(&rx_atomic_mutex);
539 retval = atomic->var;
540 MUTEX_EXIT(&rx_atomic_mutex);
546 rx_atomic_sub(rx_atomic_t *atomic, int change) {
547 MUTEX_ENTER(&rx_atomic_mutex);
548 atomic->var -= change;
549 MUTEX_EXIT(&rx_atomic_mutex);
553 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
554 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
558 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
559 MUTEX_ENTER(&rx_atomic_mutex);
560 atomic->var |= (1<<bit);
561 MUTEX_EXIT(&rx_atomic_mutex);
565 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
566 MUTEX_ENTER(&rx_atomic_mutex);
567 atomic->var &= ~(1<<bit);
568 MUTEX_EXIT(&rx_atomic_mutex);
572 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
575 MUTEX_ENTER(&rx_atomic_mutex);
577 atomic->var |= 1<<bit;
578 MUTEX_EXIT(&rx_atomic_mutex);
580 return (val & 1<<bit) == 1<<bit;
584 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
587 MUTEX_ENTER(&rx_atomic_mutex);
589 atomic->var &= ~(1<<bit);
590 MUTEX_EXIT(&rx_atomic_mutex);
592 return (val & 1<<bit) == 1<<bit;