Some doc path fixes from Anders
[pkg-k5-afs_openafs.git] / src / rx / rx_atomic.h
blob5bf35fee839f2ed44ba7692e0047dd30a7751820
1 /*
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
6 * are met:
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) }
30 #ifdef AFS_NT40_ENV
31 typedef struct {
32 volatile int var;
33 } rx_atomic_t;
35 static_inline void
36 rx_atomic_set(rx_atomic_t *atomic, int val) {
37 atomic->var = val;
40 static_inline int
41 rx_atomic_read(rx_atomic_t *atomic) {
42 return atomic->var;
45 static_inline void
46 rx_atomic_inc(rx_atomic_t *atomic) {
47 InterlockedIncrement(&atomic->var);
50 static_inline int
51 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
52 return InterlockedIncrement(&atomic->var);
55 static_inline void
56 rx_atomic_add(rx_atomic_t *atomic, int change) {
57 InterlockedExchangeAdd(&atomic->var, change);
60 static_inline int
61 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
62 return InterlockedExchangeAdd(&atomic->var, change) + change;
65 static_inline void
66 rx_atomic_dec(rx_atomic_t *atomic) {
67 InterlockedDecrement(&atomic->var);
70 static_inline int
71 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
72 return InterlockedDecrement(&atomic->var);
75 static_inline void
76 rx_atomic_sub(rx_atomic_t *atomic, int change) {
77 InterlockedExchangeAdd(&atomic->var, 0 - change);
80 static_inline int
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 */
88 static_inline void
89 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
90 (void) InterlockedBitTestAndSet(&atomic->var, bit);
93 static_inline void
94 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
95 (void) InterlockedBitTestAndReset(&atomic->var, bit);
98 static_inline int
99 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
100 return InterlockedBitTestAndSet(&atomic->var, bit);
103 static_inline int
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>
111 typedef struct {
112 volatile int var;
113 } rx_atomic_t;
115 static_inline void
116 rx_atomic_set(rx_atomic_t *atomic, int val) {
117 atomic->var = val;
120 static_inline int
121 rx_atomic_read(rx_atomic_t *atomic) {
122 return atomic->var;
125 static_inline void
126 rx_atomic_inc(rx_atomic_t *atomic) {
127 fetch_and_add(&atomic->var, 1);
130 static_inline int
131 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
132 return (fetch_and_add(&atomic->var, 1) + 1);
135 static_inline void
136 rx_atomic_add(rx_atomic_t *atomic, int change) {
137 fetch_and_add(&atomic->var, change);
140 static_inline int
141 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
142 return (fetch_and_add(&atomic->var, change) + change);
145 static_inline void
146 rx_atomic_dec(rx_atomic_t *atomic) {
147 fetch_and_add(&atomic->var, -1);
150 static_inline int
151 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
152 return (fetch_and_add(&atomic->var, -1) - 1);
155 static_inline void
156 rx_atomic_sub(rx_atomic_t *atomic, int change) {
157 fetch_and_add(&atomic->var, -change);
160 static_inline int
161 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
162 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
165 static_inline void
166 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
167 fetch_and_or(&atomic->var, 1<<bit);
170 static_inline void
171 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
172 fetch_and_and(&atomic->var, ~(1<<bit));
175 static_inline int
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;
180 static_inline int
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)
188 # define OSATOMIC_USE_INLINED 1
189 # else
191 # if defined(KERNEL) && !defined(UKERNEL)
192 # define OSAtomicIncrement32 OSIncrementAtomic
193 # define OSAtomicAdd32 OSAddAtomic
194 # define OSAtomicDecrement32 OSDecrementAtomic
195 # define OSAtomicOr32 OSBitOrAtomic
196 # define OSAtomicAnd32 OSBitAndAtomic
197 # endif
199 # endif /* end defined DARWIN160 */
201 # include <libkern/OSAtomic.h>
203 typedef struct {
204 volatile int var;
205 } rx_atomic_t;
207 static_inline void
208 rx_atomic_set(rx_atomic_t *atomic, int val) {
209 atomic->var = val;
212 static_inline int
213 rx_atomic_read(rx_atomic_t *atomic) {
214 return atomic->var;
217 static_inline void
218 rx_atomic_inc(rx_atomic_t *atomic) {
219 OSAtomicIncrement32(&atomic->var);
222 static_inline int
223 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
224 return OSAtomicIncrement32(&atomic->var);
227 static_inline void
228 rx_atomic_add(rx_atomic_t *atomic, int change) {
229 OSAtomicAdd32(change, &atomic->var);
232 static_inline int
233 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
234 return OSAtomicAdd32(change, &atomic->var);
237 static_inline void
238 rx_atomic_dec(rx_atomic_t *atomic) {
239 OSAtomicDecrement32(&atomic->var);
242 static_inline int
243 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
244 return OSAtomicDecrement32(&atomic->var);
247 static_inline void
248 rx_atomic_sub(rx_atomic_t *atomic, int change) {
249 OSAtomicAdd32(0 - change, &atomic->var);
252 static_inline int
253 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
254 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
257 static_inline void
258 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
259 OSAtomicOr32(1<<bit, (volatile uint32_t *)&atomic->var);
262 static_inline void
263 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
264 OSAtomicAnd32(~(1<<bit), (volatile uint32_t *)&atomic->var);
267 static_inline int
268 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
269 return ((OSAtomicOr32Orig(1<<bit, (volatile uint32_t *)&atomic->var) & 1<<bit)
270 != 0);
273 static_inline int
274 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
275 return ((OSAtomicAnd32Orig(~(1<<bit),
276 (volatile uint32_t *)&atomic->var) & 1<<bit)
277 != 0);
280 #elif defined(AFS_LINUX26_ENV) && defined(KERNEL)
281 #include <asm/atomic.h>
283 typedef atomic_t rx_atomic_t;
285 #define rx_atomic_set(X, V) atomic_set(X, V)
286 #define rx_atomic_read(X) atomic_read(X)
287 #define rx_atomic_inc(X) atomic_inc(X)
288 #define rx_atomic_inc_and_read(X) atomic_inc_return(X)
289 #define rx_atomic_add(X, V) atomic_add(V, X)
290 #define rx_atomic_add_and_read(X, V) atomic_add_return(V, X)
291 #define rx_atomic_dec(X) atomic_dec(X)
292 #define rx_atomic_dec_and_read(X) atomic_dec_return(X)
293 #define rx_atomic_sub(X, V) atomic_sub(V, X)
294 #define rx_atomic_test_bit(X, B) test_bit(B, (unsigned long *) &(X)->counter)
295 #define rx_atomic_set_bit(X, B) set_bit(B, (unsigned long *) &(X)->counter)
296 #define rx_atomic_clear_bit(X, B) clear_bit(B, (unsigned long *) &(X)->counter)
297 #define rx_atomic_test_and_set_bit(X, B) test_and_set_bit(B, (unsigned long *) &(X)->counter)
298 #define rx_atomic_test_and_clear_bit(X, B) test_and_clear_bit(B, (unsigned long *) &(X)->counter)
300 #elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL))
302 # if defined(KERNEL) && !defined(UKERNEL)
303 # include <sys/atomic.h>
304 # else
305 # include <atomic.h>
306 # endif
308 #ifndef AFS_SUN510_ENV
309 # define atomic_inc_32(X) atomic_add_32((X), 1)
310 # define atomic_inc_32_nv(X) atomic_add_32_nv((X), 1)
311 # define atomic_dec_32(X) atomic_add_32((X), -1)
312 # define atomic_dec_32_nv(X) atomic_add_32_nv((X), -1)
313 #endif
315 typedef struct {
316 volatile unsigned int var;
317 } rx_atomic_t;
319 static_inline void
320 rx_atomic_set(rx_atomic_t *atomic, int val) {
321 atomic->var = val;
324 static_inline int
325 rx_atomic_read(rx_atomic_t *atomic) {
326 return atomic->var;
329 static_inline void
330 rx_atomic_inc(rx_atomic_t *atomic) {
331 atomic_inc_32(&atomic->var);
334 static_inline int
335 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
336 return atomic_inc_32_nv(&atomic->var);
339 static_inline void
340 rx_atomic_add(rx_atomic_t *atomic, int change) {
341 atomic_add_32(&atomic->var, change);
344 static_inline int
345 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
346 return atomic_add_32_nv(&atomic->var, change);
349 static_inline void
350 rx_atomic_dec(rx_atomic_t *atomic) {
351 atomic_dec_32(&atomic->var);
354 static_inline int
355 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
356 return atomic_dec_32_nv(&atomic->var);
359 static_inline void
360 rx_atomic_sub(rx_atomic_t *atomic, int change) {
361 atomic_add_32(&atomic->var, 0 - change);
364 static_inline int
365 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
366 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
369 static_inline void
370 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
371 atomic_or_32(&atomic->var, 1<<bit);
374 static_inline void
375 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
376 atomic_and_32(&atomic->var, ~(1<<bit));
379 static_inline int
380 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
381 return (atomic_set_long_excl(&atomic->var, bit) == -1);
384 static_inline int
385 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
386 return (atomic_clear_long_excl(&atomic->var, bit) == 0);
389 #elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD)
391 typedef struct {
392 volatile int var;
393 } rx_atomic_t;
395 static_inline void
396 rx_atomic_set(rx_atomic_t *atomic, int val) {
397 atomic->var = val;
400 static_inline int
401 rx_atomic_read(rx_atomic_t *atomic) {
402 return atomic->var;
405 static_inline void
406 rx_atomic_inc(rx_atomic_t *atomic) {
407 (void)__sync_fetch_and_add(&atomic->var, 1);
410 static_inline int
411 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
412 return __sync_add_and_fetch(&atomic->var, 1);
415 static_inline void
416 rx_atomic_add(rx_atomic_t *atomic, int change) {
417 (void)__sync_fetch_and_add(&atomic->var, change);
420 static_inline int
421 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
422 return __sync_fetch_and_add(&atomic->var, change);
425 static_inline void
426 rx_atomic_dec(rx_atomic_t *atomic) {
427 (void)__sync_fetch_and_sub(&atomic->var, 1);
430 static_inline int
431 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
432 return __sync_sub_and_fetch(&atomic->var, 1);
435 static_inline void
436 rx_atomic_sub(rx_atomic_t *atomic, int change) {
437 (void)__sync_fetch_and_sub(&atomic->var, change);
440 static_inline int
441 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
442 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
445 static_inline void
446 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
447 (void)__sync_fetch_and_or(&atomic->var, 1<<bit);
450 static_inline void
451 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
452 (void)__sync_fetch_and_and(&atomic->var, ~(1<<bit));
455 static_inline int
456 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
457 return (__sync_fetch_and_or(&atomic->var, 1<<bit) & 1<<bit) != 0;
460 static_inline int
461 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
462 return (__sync_fetch_and_and(&atomic->var, ~(1<<bit)) & 1<<bit) != 0;
465 #else
467 /* If we're on a platform where we have no idea how to do atomics,
468 * then we fall back to using a single process wide mutex to protect
469 * all atomic variables. This won't be the quickest thing ever.
472 #ifdef RX_ENABLE_LOCKS
473 extern afs_kmutex_t rx_atomic_mutex;
474 #endif
476 typedef struct {
477 int var;
478 } rx_atomic_t;
480 static_inline void
481 rx_atomic_set(rx_atomic_t *atomic, int val) {
482 MUTEX_ENTER(&rx_atomic_mutex);
483 atomic->var = val;
484 MUTEX_EXIT(&rx_atomic_mutex);
487 static_inline int
488 rx_atomic_read(rx_atomic_t *atomic) {
489 int out;
491 MUTEX_ENTER(&rx_atomic_mutex);
492 out = atomic->var;
493 MUTEX_EXIT(&rx_atomic_mutex);
495 return out;
498 static_inline void
499 rx_atomic_inc(rx_atomic_t *atomic) {
500 MUTEX_ENTER(&rx_atomic_mutex);
501 atomic->var++;
502 MUTEX_EXIT(&rx_atomic_mutex);
505 static_inline int
506 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
507 int retval;
508 MUTEX_ENTER(&rx_atomic_mutex);
509 atomic->var++;
510 retval = atomic->var;
511 MUTEX_EXIT(&rx_atomic_mutex);
512 return retval;
515 static_inline void
516 rx_atomic_add(rx_atomic_t *atomic, int change) {
517 MUTEX_ENTER(&rx_atomic_mutex);
518 atomic->var += change;
519 MUTEX_EXIT(&rx_atomic_mutex);
522 static_inline int
523 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
524 int retval;
526 MUTEX_ENTER(&rx_atomic_mutex);
527 atomic->var += change;
528 retval = atomic->var;
529 MUTEX_EXIT(&rx_atomic_mutex);
531 return retval;
534 static_inline void
535 rx_atomic_dec(rx_atomic_t *atomic) {
536 MUTEX_ENTER(&rx_atomic_mutex);
537 atomic->var--;
538 MUTEX_EXIT(&rx_atomic_mutex);
541 static_inline int
542 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
543 int retval;
544 MUTEX_ENTER(&rx_atomic_mutex);
545 atomic->var--;
546 retval = atomic->var;
547 MUTEX_EXIT(&rx_atomic_mutex);
548 return retval;
552 static_inline void
553 rx_atomic_sub(rx_atomic_t *atomic, int change) {
554 MUTEX_ENTER(&rx_atomic_mutex);
555 atomic->var -= change;
556 MUTEX_EXIT(&rx_atomic_mutex);
559 static_inline int
560 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
561 return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
564 static_inline void
565 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
566 MUTEX_ENTER(&rx_atomic_mutex);
567 atomic->var |= (1<<bit);
568 MUTEX_EXIT(&rx_atomic_mutex);
571 static_inline void
572 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
573 MUTEX_ENTER(&rx_atomic_mutex);
574 atomic->var &= ~(1<<bit);
575 MUTEX_EXIT(&rx_atomic_mutex);
578 static_inline int
579 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
580 int val;
582 MUTEX_ENTER(&rx_atomic_mutex);
583 val = atomic->var;
584 atomic->var |= 1<<bit;
585 MUTEX_EXIT(&rx_atomic_mutex);
587 return (val & 1<<bit) == 1<<bit;
590 static_inline int
591 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
592 int val;
594 MUTEX_ENTER(&rx_atomic_mutex);
595 val = atomic->var;
596 atomic->var &= ~(1<<bit);
597 MUTEX_EXIT(&rx_atomic_mutex);
599 return (val & 1<<bit) == 1<<bit;
601 #endif
603 #endif