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 # if (defined(AFS_DARWIN160_ENV) || defined(AFS_USR_DARWIN160_ENV)) && !defined(KERNEL)
188 # define OSATOMIC_USE_INLINED 1
191 # include <libkern/OSAtomic.h>
193 # if defined(KERNEL) && !defined(UKERNEL)
195 OSAtomicIncrement32(volatile int *value
)
197 return OSIncrementAtomic(value
) + 1;
201 OSAtomicAdd32(int amount
, volatile int *value
)
203 return OSAddAtomic(amount
, value
) + amount
;
207 OSAtomicDecrement32(volatile int *value
)
209 return OSDecrementAtomic(value
) - 1;
212 static_inline
unsigned int
213 OSAtomicOr32(unsigned int mask
, volatile unsigned int *value
)
215 return OSBitOrAtomic(mask
, value
) | mask
;
218 static_inline
unsigned int
219 OSAtomicAnd32(unsigned int mask
, volatile unsigned int *value
)
221 return OSBitAndAtomic(mask
, value
) & mask
;
223 #define OSAtomicOr32Orig OSBitOrAtomic
224 #define OSAtomicAnd32Orig OSBitAndAtomic
232 rx_atomic_set(rx_atomic_t
*atomic
, int val
) {
237 rx_atomic_read(rx_atomic_t
*atomic
) {
242 rx_atomic_inc(rx_atomic_t
*atomic
) {
243 OSAtomicIncrement32(&atomic
->var
);
247 rx_atomic_inc_and_read(rx_atomic_t
*atomic
) {
248 return OSAtomicIncrement32(&atomic
->var
);
252 rx_atomic_add(rx_atomic_t
*atomic
, int change
) {
253 OSAtomicAdd32(change
, &atomic
->var
);
257 rx_atomic_add_and_read(rx_atomic_t
*atomic
, int change
) {
258 return OSAtomicAdd32(change
, &atomic
->var
);
262 rx_atomic_dec(rx_atomic_t
*atomic
) {
263 OSAtomicDecrement32(&atomic
->var
);
267 rx_atomic_dec_and_read(rx_atomic_t
*atomic
) {
268 return OSAtomicDecrement32(&atomic
->var
);
272 rx_atomic_sub(rx_atomic_t
*atomic
, int change
) {
273 OSAtomicAdd32(0 - change
, &atomic
->var
);
277 rx_atomic_test_bit(rx_atomic_t
*atomic
, int bit
) {
278 return ((unsigned int) rx_atomic_read(atomic
) & 1<<bit
) != 0;
282 rx_atomic_set_bit(rx_atomic_t
*atomic
, int bit
) {
283 OSAtomicOr32(1<<bit
, (volatile uint32_t *)&atomic
->var
);
287 rx_atomic_clear_bit(rx_atomic_t
*atomic
, int bit
) {
288 OSAtomicAnd32(~(1<<bit
), (volatile uint32_t *)&atomic
->var
);
292 rx_atomic_test_and_set_bit(rx_atomic_t
*atomic
, int bit
) {
293 return ((OSAtomicOr32Orig(1<<bit
, (volatile uint32_t *)&atomic
->var
) & 1<<bit
)
298 rx_atomic_test_and_clear_bit(rx_atomic_t
*atomic
, int bit
) {
299 return ((OSAtomicAnd32Orig(~(1<<bit
),
300 (volatile uint32_t *)&atomic
->var
) & 1<<bit
)
304 #elif defined(AFS_LINUX26_ENV) && defined(KERNEL)
305 #include <asm/atomic.h>
307 typedef atomic_t rx_atomic_t
;
309 #define rx_atomic_set(X, V) atomic_set(X, V)
310 #define rx_atomic_read(X) atomic_read(X)
311 #define rx_atomic_inc(X) atomic_inc(X)
312 #define rx_atomic_inc_and_read(X) atomic_inc_return(X)
313 #define rx_atomic_add(X, V) atomic_add(V, X)
314 #define rx_atomic_add_and_read(X, V) atomic_add_return(V, X)
315 #define rx_atomic_dec(X) atomic_dec(X)
316 #define rx_atomic_dec_and_read(X) atomic_dec_return(X)
317 #define rx_atomic_sub(X, V) atomic_sub(V, X)
318 #define rx_atomic_test_bit(X, B) test_bit(B, (unsigned long *) &(X)->counter)
319 #define rx_atomic_set_bit(X, B) set_bit(B, (unsigned long *) &(X)->counter)
320 #define rx_atomic_clear_bit(X, B) clear_bit(B, (unsigned long *) &(X)->counter)
321 #define rx_atomic_test_and_set_bit(X, B) test_and_set_bit(B, (unsigned long *) &(X)->counter)
322 #define rx_atomic_test_and_clear_bit(X, B) test_and_clear_bit(B, (unsigned long *) &(X)->counter)
324 #elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL))
326 # if defined(KERNEL) && !defined(UKERNEL)
327 # include <sys/atomic.h>
332 #ifndef AFS_SUN510_ENV
333 # define atomic_inc_32(X) atomic_add_32((X), 1)
334 # define atomic_inc_32_nv(X) atomic_add_32_nv((X), 1)
335 # define atomic_dec_32(X) atomic_add_32((X), -1)
336 # define atomic_dec_32_nv(X) atomic_add_32_nv((X), -1)
340 volatile unsigned int var
;
344 rx_atomic_set(rx_atomic_t
*atomic
, int val
) {
349 rx_atomic_read(rx_atomic_t
*atomic
) {
354 rx_atomic_inc(rx_atomic_t
*atomic
) {
355 atomic_inc_32(&atomic
->var
);
359 rx_atomic_inc_and_read(rx_atomic_t
*atomic
) {
360 return atomic_inc_32_nv(&atomic
->var
);
364 rx_atomic_add(rx_atomic_t
*atomic
, int change
) {
365 atomic_add_32(&atomic
->var
, change
);
369 rx_atomic_add_and_read(rx_atomic_t
*atomic
, int change
) {
370 return atomic_add_32_nv(&atomic
->var
, change
);
374 rx_atomic_dec(rx_atomic_t
*atomic
) {
375 atomic_dec_32(&atomic
->var
);
379 rx_atomic_dec_and_read(rx_atomic_t
*atomic
) {
380 return atomic_dec_32_nv(&atomic
->var
);
384 rx_atomic_sub(rx_atomic_t
*atomic
, int change
) {
385 atomic_add_32(&atomic
->var
, 0 - change
);
389 rx_atomic_test_bit(rx_atomic_t
*atomic
, int bit
) {
390 return ((unsigned int) rx_atomic_read(atomic
) & 1<<bit
) != 0;
394 rx_atomic_set_bit(rx_atomic_t
*atomic
, int bit
) {
395 atomic_or_32(&atomic
->var
, 1<<bit
);
399 rx_atomic_clear_bit(rx_atomic_t
*atomic
, int bit
) {
400 atomic_and_32(&atomic
->var
, ~(1<<bit
));
404 rx_atomic_test_and_set_bit(rx_atomic_t
*atomic
, int bit
) {
405 return (atomic_set_long_excl(&atomic
->var
, bit
) == -1);
409 rx_atomic_test_and_clear_bit(rx_atomic_t
*atomic
, int bit
) {
410 return (atomic_clear_long_excl(&atomic
->var
, bit
) == 0);
413 #elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD)
420 rx_atomic_set(rx_atomic_t
*atomic
, int val
) {
425 rx_atomic_read(rx_atomic_t
*atomic
) {
430 rx_atomic_inc(rx_atomic_t
*atomic
) {
431 (void)__sync_fetch_and_add(&atomic
->var
, 1);
435 rx_atomic_inc_and_read(rx_atomic_t
*atomic
) {
436 return __sync_add_and_fetch(&atomic
->var
, 1);
440 rx_atomic_add(rx_atomic_t
*atomic
, int change
) {
441 (void)__sync_fetch_and_add(&atomic
->var
, change
);
445 rx_atomic_add_and_read(rx_atomic_t
*atomic
, int change
) {
446 return __sync_fetch_and_add(&atomic
->var
, change
);
450 rx_atomic_dec(rx_atomic_t
*atomic
) {
451 (void)__sync_fetch_and_sub(&atomic
->var
, 1);
455 rx_atomic_dec_and_read(rx_atomic_t
*atomic
) {
456 return __sync_sub_and_fetch(&atomic
->var
, 1);
460 rx_atomic_sub(rx_atomic_t
*atomic
, int change
) {
461 (void)__sync_fetch_and_sub(&atomic
->var
, change
);
465 rx_atomic_test_bit(rx_atomic_t
*atomic
, int bit
) {
466 return ((unsigned int) rx_atomic_read(atomic
) & 1<<bit
) != 0;
470 rx_atomic_set_bit(rx_atomic_t
*atomic
, int bit
) {
471 (void)__sync_fetch_and_or(&atomic
->var
, 1<<bit
);
475 rx_atomic_clear_bit(rx_atomic_t
*atomic
, int bit
) {
476 (void)__sync_fetch_and_and(&atomic
->var
, ~(1<<bit
));
480 rx_atomic_test_and_set_bit(rx_atomic_t
*atomic
, int bit
) {
481 return (__sync_fetch_and_or(&atomic
->var
, 1<<bit
) & 1<<bit
) != 0;
485 rx_atomic_test_and_clear_bit(rx_atomic_t
*atomic
, int bit
) {
486 return (__sync_fetch_and_and(&atomic
->var
, ~(1<<bit
)) & 1<<bit
) != 0;
491 /* If we're on a platform where we have no idea how to do atomics,
492 * then we fall back to using a single process wide mutex to protect
493 * all atomic variables. This won't be the quickest thing ever.
496 #ifdef RX_ENABLE_LOCKS
497 extern afs_kmutex_t rx_atomic_mutex
;
505 rx_atomic_set(rx_atomic_t
*atomic
, int val
) {
506 MUTEX_ENTER(&rx_atomic_mutex
);
508 MUTEX_EXIT(&rx_atomic_mutex
);
512 rx_atomic_read(rx_atomic_t
*atomic
) {
515 MUTEX_ENTER(&rx_atomic_mutex
);
517 MUTEX_EXIT(&rx_atomic_mutex
);
523 rx_atomic_inc(rx_atomic_t
*atomic
) {
524 MUTEX_ENTER(&rx_atomic_mutex
);
526 MUTEX_EXIT(&rx_atomic_mutex
);
530 rx_atomic_inc_and_read(rx_atomic_t
*atomic
) {
532 MUTEX_ENTER(&rx_atomic_mutex
);
534 retval
= atomic
->var
;
535 MUTEX_EXIT(&rx_atomic_mutex
);
540 rx_atomic_add(rx_atomic_t
*atomic
, int change
) {
541 MUTEX_ENTER(&rx_atomic_mutex
);
542 atomic
->var
+= change
;
543 MUTEX_EXIT(&rx_atomic_mutex
);
547 rx_atomic_add_and_read(rx_atomic_t
*atomic
, int change
) {
550 MUTEX_ENTER(&rx_atomic_mutex
);
551 atomic
->var
+= change
;
552 retval
= atomic
->var
;
553 MUTEX_EXIT(&rx_atomic_mutex
);
559 rx_atomic_dec(rx_atomic_t
*atomic
) {
560 MUTEX_ENTER(&rx_atomic_mutex
);
562 MUTEX_EXIT(&rx_atomic_mutex
);
566 rx_atomic_dec_and_read(rx_atomic_t
*atomic
) {
568 MUTEX_ENTER(&rx_atomic_mutex
);
570 retval
= atomic
->var
;
571 MUTEX_EXIT(&rx_atomic_mutex
);
577 rx_atomic_sub(rx_atomic_t
*atomic
, int change
) {
578 MUTEX_ENTER(&rx_atomic_mutex
);
579 atomic
->var
-= change
;
580 MUTEX_EXIT(&rx_atomic_mutex
);
584 rx_atomic_test_bit(rx_atomic_t
*atomic
, int bit
) {
585 return ((unsigned int) rx_atomic_read(atomic
) & 1<<bit
) != 0;
589 rx_atomic_set_bit(rx_atomic_t
*atomic
, int bit
) {
590 MUTEX_ENTER(&rx_atomic_mutex
);
591 atomic
->var
|= (1<<bit
);
592 MUTEX_EXIT(&rx_atomic_mutex
);
596 rx_atomic_clear_bit(rx_atomic_t
*atomic
, int bit
) {
597 MUTEX_ENTER(&rx_atomic_mutex
);
598 atomic
->var
&= ~(1<<bit
);
599 MUTEX_EXIT(&rx_atomic_mutex
);
603 rx_atomic_test_and_set_bit(rx_atomic_t
*atomic
, int bit
) {
606 MUTEX_ENTER(&rx_atomic_mutex
);
608 atomic
->var
|= 1<<bit
;
609 MUTEX_EXIT(&rx_atomic_mutex
);
611 return (val
& 1<<bit
) == 1<<bit
;
615 rx_atomic_test_and_clear_bit(rx_atomic_t
*atomic
, int bit
) {
618 MUTEX_ENTER(&rx_atomic_mutex
);
620 atomic
->var
&= ~(1<<bit
);
621 MUTEX_EXIT(&rx_atomic_mutex
);
623 return (val
& 1<<bit
) == 1<<bit
;