doc: update information about vlserver logging
[openafs.git] / src / rx / rx_atomic.h
1 /*
2  * Copyright (c) 2010 Your Filesystem Inc. All rights reserved.
3  *
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.
12  *
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.
23  */
24
25 #ifndef OPENAFS_RX_ATOMIC_H
26 #define OPENAFS_RX_ATOMIC_H 1
27
28 #define RX_ATOMIC_INIT(i) { (i) }
29
30 #ifdef AFS_NT40_ENV
31 typedef struct {
32     volatile int var;
33 } rx_atomic_t;
34
35 static_inline void
36 rx_atomic_set(rx_atomic_t *atomic, int val) {
37     atomic->var = val;
38 }
39
40 static_inline int
41 rx_atomic_read(rx_atomic_t *atomic) {
42     return atomic->var;
43 }
44
45 static_inline void
46 rx_atomic_inc(rx_atomic_t *atomic) {
47     InterlockedIncrement(&atomic->var);
48 }
49
50 static_inline int
51 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
52     return InterlockedIncrement(&atomic->var);
53 }
54
55 static_inline void
56 rx_atomic_add(rx_atomic_t *atomic, int change) {
57     InterlockedExchangeAdd(&atomic->var, change);
58 }
59
60 static_inline int
61 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
62     return InterlockedExchangeAdd(&atomic->var, change) + change;
63 }
64
65 static_inline void
66 rx_atomic_dec(rx_atomic_t *atomic) {
67     InterlockedDecrement(&atomic->var);
68 }
69
70 static_inline int
71 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
72     return InterlockedDecrement(&atomic->var);
73 }
74
75 static_inline void
76 rx_atomic_sub(rx_atomic_t *atomic, int change) {
77     InterlockedExchangeAdd(&atomic->var, 0 - change);
78 }
79
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;
83 }
84
85 /* No InterlockedOr or InterlockedAnd on ix86, so just use the
86  * BitTest functions */
87
88 static_inline void
89 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
90     (void) InterlockedBitTestAndSet(&atomic->var, bit);
91 }
92
93 static_inline void
94 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
95     (void) InterlockedBitTestAndReset(&atomic->var, bit);
96 }
97
98 static_inline int
99 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
100     return InterlockedBitTestAndSet(&atomic->var, bit);
101 }
102
103 static_inline int
104 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
105     return InterlockedBitTestAndReset(&atomic->var, bit);
106 }
107
108 #elif defined(AFS_AIX61_ENV) || defined(AFS_USR_AIX61_ENV)
109 #include <sys/atomic_op.h>
110
111 typedef struct {
112    volatile int var;
113 } rx_atomic_t;
114
115 static_inline void
116 rx_atomic_set(rx_atomic_t *atomic, int val) {
117     atomic->var = val;
118 }
119
120 static_inline int
121 rx_atomic_read(rx_atomic_t *atomic) {
122     return atomic->var;
123 }
124
125 static_inline void
126 rx_atomic_inc(rx_atomic_t *atomic) {
127     fetch_and_add(&atomic->var, 1);
128 }
129
130 static_inline int
131 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
132     return (fetch_and_add(&atomic->var, 1) + 1);
133 }
134
135 static_inline void
136 rx_atomic_add(rx_atomic_t *atomic, int change) {
137     fetch_and_add(&atomic->var, change);
138 }
139
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);
143 }
144
145 static_inline void
146 rx_atomic_dec(rx_atomic_t *atomic) {
147     fetch_and_add(&atomic->var, -1);
148 }
149
150 static_inline int
151 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
152     return (fetch_and_add(&atomic->var, -1) - 1);
153 }
154
155 static_inline void
156 rx_atomic_sub(rx_atomic_t *atomic, int change) {
157     fetch_and_add(&atomic->var, -change);
158 }
159
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;
163 }
164
165 static_inline void
166 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
167     fetch_and_or(&atomic->var, 1<<bit);
168 }
169
170 static_inline void
171 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
172     fetch_and_and(&atomic->var, ~(1<<bit));
173 }
174
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;
178 }
179
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;
183 }
184
185 #elif defined(AFS_DARWIN80_ENV) || defined(AFS_USR_DARWIN80_ENV)
186
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
194 #endif
195
196 typedef struct {
197     volatile int var;
198 } rx_atomic_t;
199
200 static_inline void
201 rx_atomic_set(rx_atomic_t *atomic, int val) {
202     atomic->var = val;
203 }
204
205 static_inline int
206 rx_atomic_read(rx_atomic_t *atomic) {
207     return atomic->var;
208 }
209
210 static_inline void
211 rx_atomic_inc(rx_atomic_t *atomic) {
212     OSAtomicIncrement32(&atomic->var);
213 }
214
215 static_inline int
216 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
217     return OSAtomicIncrement32(&atomic->var);
218 }
219
220 static_inline void
221 rx_atomic_add(rx_atomic_t *atomic, int change) {
222     OSAtomicAdd32(change, &atomic->var);
223 }
224
225 static_inline int
226 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
227     return OSAtomicAdd32(change, &atomic->var);
228 }
229
230 static_inline void
231 rx_atomic_dec(rx_atomic_t *atomic) {
232     OSAtomicDecrement32(&atomic->var);
233 }
234
235 static_inline int
236 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
237     return OSAtomicDecrement32(&atomic->var);
238 }
239
240 static_inline void
241 rx_atomic_sub(rx_atomic_t *atomic, int change) {
242     OSAtomicAdd32(0 - change, &atomic->var);
243 }
244
245 static_inline int
246 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
247     return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
248 }
249
250 static_inline void
251 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
252     OSAtomicOr32(1<<bit, (volatile uint32_t *)&atomic->var);
253 }
254
255 static_inline void
256 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
257     OSAtomicAnd32(~(1<<bit), (volatile uint32_t *)&atomic->var);
258 }
259
260 static_inline int
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)
263                 != 0);
264 }
265
266 static_inline int
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)
270             != 0);
271 }
272
273 #elif defined(AFS_LINUX26_ENV) && defined(KERNEL)
274 #include <asm/atomic.h>
275
276 typedef atomic_t rx_atomic_t;
277
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)
292
293 #elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL))
294
295 # if defined(KERNEL) && !defined(UKERNEL)
296 #  include <sys/atomic.h>
297 # else
298 #  include <atomic.h>
299 # endif
300
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)
306 #endif
307
308 typedef struct {
309     volatile unsigned int var;
310 } rx_atomic_t;
311
312 static_inline void
313 rx_atomic_set(rx_atomic_t *atomic, int val) {
314     atomic->var = val;
315 }
316
317 static_inline int
318 rx_atomic_read(rx_atomic_t *atomic) {
319     return atomic->var;
320 }
321
322 static_inline void
323 rx_atomic_inc(rx_atomic_t *atomic) {
324     atomic_inc_32(&atomic->var);
325 }
326
327 static_inline int
328 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
329     return atomic_inc_32_nv(&atomic->var);
330 }
331
332 static_inline void
333 rx_atomic_add(rx_atomic_t *atomic, int change) {
334     atomic_add_32(&atomic->var, change);
335 }
336
337 static_inline int
338 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
339     return atomic_add_32_nv(&atomic->var, change);
340 }
341
342 static_inline void
343 rx_atomic_dec(rx_atomic_t *atomic) {
344     atomic_dec_32(&atomic->var);
345 }
346
347 static_inline int
348 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
349     return atomic_dec_32_nv(&atomic->var);
350 }
351
352 static_inline void
353 rx_atomic_sub(rx_atomic_t *atomic, int change) {
354     atomic_add_32(&atomic->var, 0 - change);
355 }
356
357 static_inline int
358 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
359     return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
360 }
361
362 static_inline void
363 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
364     atomic_or_32(&atomic->var, 1<<bit);
365 }
366
367 static_inline void
368 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
369     atomic_and_32(&atomic->var, ~(1<<bit));
370 }
371
372 static_inline int
373 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
374     return (atomic_set_long_excl(&atomic->var, bit) == -1);
375 }
376
377 static_inline int
378 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
379     return (atomic_clear_long_excl(&atomic->var, bit) == 0);
380 }
381
382 #elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD)
383
384 typedef struct {
385    volatile int var;
386 } rx_atomic_t;
387
388 static_inline void
389 rx_atomic_set(rx_atomic_t *atomic, int val) {
390     atomic->var = val;
391 }
392
393 static_inline int
394 rx_atomic_read(rx_atomic_t *atomic) {
395     return atomic->var;
396 }
397
398 static_inline void
399 rx_atomic_inc(rx_atomic_t *atomic) {
400     (void)__sync_fetch_and_add(&atomic->var, 1);
401 }
402
403 static_inline int
404 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
405     return __sync_add_and_fetch(&atomic->var, 1);
406 }
407
408 static_inline void
409 rx_atomic_add(rx_atomic_t *atomic, int change) {
410     (void)__sync_fetch_and_add(&atomic->var, change);
411 }
412
413 static_inline int
414 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
415     return __sync_fetch_and_add(&atomic->var, change);
416 }
417
418 static_inline void
419 rx_atomic_dec(rx_atomic_t *atomic) {
420     (void)__sync_fetch_and_sub(&atomic->var, 1);
421 }
422
423 static_inline int
424 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
425     return __sync_sub_and_fetch(&atomic->var, 1);
426 }
427
428 static_inline void
429 rx_atomic_sub(rx_atomic_t *atomic, int change) {
430     (void)__sync_fetch_and_sub(&atomic->var, change);
431 }
432
433 static_inline int
434 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
435     return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
436 }
437
438 static_inline void
439 rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
440     (void)__sync_fetch_and_or(&atomic->var, 1<<bit);
441 }
442
443 static_inline void
444 rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
445     (void)__sync_fetch_and_and(&atomic->var, ~(1<<bit));
446 }
447
448 static_inline int
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;
451 }
452
453 static_inline int
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;
456 }
457
458 #else
459
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.
463  */
464
465 #ifdef RX_ENABLE_LOCKS
466 extern afs_kmutex_t rx_atomic_mutex;
467 #endif
468
469 typedef struct {
470     int var;
471 } rx_atomic_t;
472
473 static_inline void
474 rx_atomic_set(rx_atomic_t *atomic, int val) {
475     MUTEX_ENTER(&rx_atomic_mutex);
476     atomic->var = val;
477     MUTEX_EXIT(&rx_atomic_mutex);
478 }
479
480 static_inline int
481 rx_atomic_read(rx_atomic_t *atomic) {
482     int out;
483
484     MUTEX_ENTER(&rx_atomic_mutex);
485     out = atomic->var;
486     MUTEX_EXIT(&rx_atomic_mutex);
487
488     return out;
489 }
490
491 static_inline void
492 rx_atomic_inc(rx_atomic_t *atomic) {
493    MUTEX_ENTER(&rx_atomic_mutex);
494    atomic->var++;
495    MUTEX_EXIT(&rx_atomic_mutex);
496 }
497
498 static_inline int
499 rx_atomic_inc_and_read(rx_atomic_t *atomic) {
500     int retval;
501     MUTEX_ENTER(&rx_atomic_mutex);
502     atomic->var++;
503     retval = atomic->var;
504     MUTEX_EXIT(&rx_atomic_mutex);
505     return retval;
506 }
507
508 static_inline void
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);
513 }
514
515 static_inline int
516 rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
517     int retval;
518
519     MUTEX_ENTER(&rx_atomic_mutex);
520     atomic->var += change;
521     retval = atomic->var;
522     MUTEX_EXIT(&rx_atomic_mutex);
523
524     return retval;
525 }
526
527 static_inline void
528 rx_atomic_dec(rx_atomic_t *atomic) {
529     MUTEX_ENTER(&rx_atomic_mutex);
530     atomic->var--;
531     MUTEX_EXIT(&rx_atomic_mutex);
532 }
533
534 static_inline int
535 rx_atomic_dec_and_read(rx_atomic_t *atomic) {
536     int retval;
537     MUTEX_ENTER(&rx_atomic_mutex);
538     atomic->var--;
539     retval = atomic->var;
540     MUTEX_EXIT(&rx_atomic_mutex);
541     return retval;
542 }
543
544
545 static_inline void
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);
550 }
551
552 static_inline int
553 rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
554     return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
555 }
556
557 static_inline void
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);
562 }
563
564 static_inline void
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);
569 }
570
571 static_inline int
572 rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
573     int val;
574
575     MUTEX_ENTER(&rx_atomic_mutex);
576     val = atomic->var;
577     atomic->var |= 1<<bit;
578     MUTEX_EXIT(&rx_atomic_mutex);
579
580     return (val & 1<<bit) == 1<<bit;
581 }
582
583 static_inline int
584 rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
585     int val;
586
587     MUTEX_ENTER(&rx_atomic_mutex);
588     val = atomic->var;
589     atomic->var &= ~(1<<bit);
590     MUTEX_EXIT(&rx_atomic_mutex);
591
592     return (val & 1<<bit) == 1<<bit;
593 }
594 #endif
595
596 #endif