tests: Add tests for checking race conditions
[urcu.git] / include / urcu / uatomic / generic.h
... / ...
CommitLineData
1// SPDX-FileCopyrightText: 1991-1994 by Xerox Corporation. All rights reserved.
2// SPDX-FileCopyrightText: 1996-1999 by Silicon Graphics. All rights reserved.
3// SPDX-FileCopyrightText: 1999-2004 Hewlett-Packard Development Company, L.P.
4// SPDX-FileCopyrightText: 2009 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5// SPDX-FileCopyrightText: 2010 Paolo Bonzini
6//
7// SPDX-License-Identifier: LicenseRef-Boehm-GC
8
9#ifndef _URCU_UATOMIC_GENERIC_H
10#define _URCU_UATOMIC_GENERIC_H
11
12/*
13 * Code inspired from libuatomic_ops-1.2, inherited in part from the
14 * Boehm-Demers-Weiser conservative garbage collector.
15 */
16
17#include <stdint.h>
18#include <urcu/compiler.h>
19#include <urcu/system.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
25#ifndef uatomic_set
26#define uatomic_set(addr, v) ((void) CMM_STORE_SHARED(*(addr), (v)))
27#endif
28
29extern void abort(void);
30
31#define uatomic_load_store_return_op(op, addr, v, mo) \
32 __extension__ \
33 ({ \
34 \
35 switch (mo) { \
36 case CMM_ACQUIRE: \
37 case CMM_CONSUME: \
38 case CMM_RELAXED: \
39 break; \
40 case CMM_RELEASE: \
41 case CMM_ACQ_REL: \
42 case CMM_SEQ_CST: \
43 case CMM_SEQ_CST_FENCE: \
44 cmm_smp_mb(); \
45 break; \
46 default: \
47 abort(); \
48 } \
49 \
50 __typeof__((*addr)) _value = op(addr, v); \
51 \
52 switch (mo) { \
53 case CMM_CONSUME: \
54 cmm_smp_read_barrier_depends(); \
55 break; \
56 case CMM_ACQUIRE: \
57 case CMM_ACQ_REL: \
58 case CMM_SEQ_CST: \
59 case CMM_SEQ_CST_FENCE: \
60 cmm_smp_mb(); \
61 break; \
62 case CMM_RELAXED: \
63 case CMM_RELEASE: \
64 break; \
65 default: \
66 abort(); \
67 } \
68 _value; \
69 })
70
71#define uatomic_load_store_op(op, addr, v, mo) \
72 do { \
73 switch (mo) { \
74 case CMM_ACQUIRE: \
75 case CMM_CONSUME: \
76 case CMM_RELAXED: \
77 break; \
78 case CMM_RELEASE: \
79 case CMM_ACQ_REL: \
80 case CMM_SEQ_CST: \
81 case CMM_SEQ_CST_FENCE: \
82 cmm_smp_mb(); \
83 break; \
84 default: \
85 abort(); \
86 } \
87 \
88 op(addr, v); \
89 \
90 switch (mo) { \
91 case CMM_CONSUME: \
92 cmm_smp_read_barrier_depends(); \
93 break; \
94 case CMM_ACQUIRE: \
95 case CMM_ACQ_REL: \
96 case CMM_SEQ_CST: \
97 case CMM_SEQ_CST_FENCE: \
98 cmm_smp_mb(); \
99 break; \
100 case CMM_RELAXED: \
101 case CMM_RELEASE: \
102 break; \
103 default: \
104 abort(); \
105 } \
106 } while (0)
107
108#define uatomic_store(addr, v, mo) \
109 do { \
110 switch (mo) { \
111 case CMM_RELAXED: \
112 break; \
113 case CMM_RELEASE: \
114 case CMM_SEQ_CST: \
115 case CMM_SEQ_CST_FENCE: \
116 cmm_smp_mb(); \
117 break; \
118 default: \
119 abort(); \
120 } \
121 \
122 uatomic_set(addr, v); \
123 \
124 switch (mo) { \
125 case CMM_RELAXED: \
126 case CMM_RELEASE: \
127 break; \
128 case CMM_SEQ_CST: \
129 case CMM_SEQ_CST_FENCE: \
130 cmm_smp_mb(); \
131 break; \
132 default: \
133 abort(); \
134 } \
135 } while (0)
136
137#define uatomic_and_mo(addr, v, mo) \
138 uatomic_load_store_op(uatomic_and, addr, v, mo)
139
140#define uatomic_or_mo(addr, v, mo) \
141 uatomic_load_store_op(uatomic_or, addr, v, mo)
142
143#define uatomic_add_mo(addr, v, mo) \
144 uatomic_load_store_op(uatomic_add, addr, v, mo)
145
146#define uatomic_sub_mo(addr, v, mo) \
147 uatomic_load_store_op(uatomic_sub, addr, v, mo)
148
149#define uatomic_inc_mo(addr, mo) \
150 uatomic_load_store_op(uatomic_add, addr, 1, mo)
151
152#define uatomic_dec_mo(addr, mo) \
153 uatomic_load_store_op(uatomic_add, addr, -1, mo)
154/*
155 * NOTE: We can not just do switch (_value == (old) ? mos : mof) otherwise the
156 * compiler emit a -Wduplicated-cond warning.
157 */
158#define uatomic_cmpxchg_mo(addr, old, new, mos, mof) \
159 __extension__ \
160 ({ \
161 switch (mos) { \
162 case CMM_ACQUIRE: \
163 case CMM_CONSUME: \
164 case CMM_RELAXED: \
165 break; \
166 case CMM_RELEASE: \
167 case CMM_ACQ_REL: \
168 case CMM_SEQ_CST: \
169 case CMM_SEQ_CST_FENCE: \
170 cmm_smp_mb(); \
171 break; \
172 default: \
173 abort(); \
174 } \
175 \
176 __typeof__(*(addr)) _value = uatomic_cmpxchg(addr, old, \
177 new); \
178 \
179 if (_value == (old)) { \
180 switch (mos) { \
181 case CMM_CONSUME: \
182 cmm_smp_read_barrier_depends(); \
183 break; \
184 case CMM_ACQUIRE: \
185 case CMM_ACQ_REL: \
186 case CMM_SEQ_CST: \
187 case CMM_SEQ_CST_FENCE: \
188 cmm_smp_mb(); \
189 break; \
190 case CMM_RELAXED: \
191 case CMM_RELEASE: \
192 break; \
193 default: \
194 abort(); \
195 } \
196 } else { \
197 switch (mof) { \
198 case CMM_CONSUME: \
199 cmm_smp_read_barrier_depends(); \
200 break; \
201 case CMM_ACQUIRE: \
202 case CMM_ACQ_REL: \
203 case CMM_SEQ_CST: \
204 case CMM_SEQ_CST_FENCE: \
205 cmm_smp_mb(); \
206 break; \
207 case CMM_RELAXED: \
208 case CMM_RELEASE: \
209 break; \
210 default: \
211 abort(); \
212 } \
213 } \
214 _value; \
215 })
216
217#define uatomic_xchg_mo(addr, v, mo) \
218 uatomic_load_store_return_op(uatomic_xchg, addr, v, mo)
219
220#define uatomic_add_return_mo(addr, v, mo) \
221 uatomic_load_store_return_op(uatomic_add_return, addr, v)
222
223#define uatomic_sub_return_mo(addr, v, mo) \
224 uatomic_load_store_return_op(uatomic_sub_return, addr, v)
225
226
227#ifndef uatomic_read
228#define uatomic_read(addr) CMM_LOAD_SHARED(*(addr))
229#endif
230
231#define uatomic_load(addr, mo) \
232 __extension__ \
233 ({ \
234 switch (mo) { \
235 case CMM_ACQUIRE: \
236 case CMM_CONSUME: \
237 case CMM_RELAXED: \
238 break; \
239 case CMM_SEQ_CST: \
240 case CMM_SEQ_CST_FENCE: \
241 cmm_smp_mb(); \
242 break; \
243 default: \
244 abort(); \
245 } \
246 \
247 __typeof__(*(addr)) _rcu_value = uatomic_read(addr); \
248 \
249 switch (mo) { \
250 case CMM_RELAXED: \
251 break; \
252 case CMM_CONSUME: \
253 cmm_smp_read_barrier_depends(); \
254 break; \
255 case CMM_ACQUIRE: \
256 case CMM_SEQ_CST: \
257 case CMM_SEQ_CST_FENCE: \
258 cmm_smp_mb(); \
259 break; \
260 default: \
261 abort(); \
262 } \
263 \
264 _rcu_value; \
265 })
266
267#if !defined __OPTIMIZE__ || defined UATOMIC_NO_LINK_ERROR
268#ifdef ILLEGAL_INSTR
269static inline __attribute__((always_inline))
270void _uatomic_link_error(void)
271{
272 /*
273 * generate an illegal instruction. Cannot catch this with
274 * linker tricks when optimizations are disabled.
275 */
276 __asm__ __volatile__(ILLEGAL_INSTR);
277}
278#else
279static inline __attribute__((always_inline, __noreturn__))
280void _uatomic_link_error(void)
281{
282 __builtin_trap();
283}
284#endif
285
286#else /* #if !defined __OPTIMIZE__ || defined UATOMIC_NO_LINK_ERROR */
287extern void _uatomic_link_error(void);
288#endif /* #else #if !defined __OPTIMIZE__ || defined UATOMIC_NO_LINK_ERROR */
289
290/* cmpxchg */
291
292#ifndef uatomic_cmpxchg
293static inline __attribute__((always_inline))
294unsigned long _uatomic_cmpxchg(void *addr, unsigned long old,
295 unsigned long _new, int len)
296{
297 switch (len) {
298#ifdef UATOMIC_HAS_ATOMIC_BYTE
299 case 1:
300 return __sync_val_compare_and_swap_1((uint8_t *) addr, old,
301 _new);
302#endif
303#ifdef UATOMIC_HAS_ATOMIC_SHORT
304 case 2:
305 return __sync_val_compare_and_swap_2((uint16_t *) addr, old,
306 _new);
307#endif
308 case 4:
309 return __sync_val_compare_and_swap_4((uint32_t *) addr, old,
310 _new);
311#if (CAA_BITS_PER_LONG == 64)
312 case 8:
313 return __sync_val_compare_and_swap_8((uint64_t *) addr, old,
314 _new);
315#endif
316 }
317 _uatomic_link_error();
318 return 0;
319}
320
321
322#define uatomic_cmpxchg(addr, old, _new) \
323 ((__typeof__(*(addr))) _uatomic_cmpxchg((addr), \
324 caa_cast_long_keep_sign(old), \
325 caa_cast_long_keep_sign(_new),\
326 sizeof(*(addr))))
327
328
329/* uatomic_and */
330
331#ifndef uatomic_and
332static inline __attribute__((always_inline))
333void _uatomic_and(void *addr, unsigned long val,
334 int len)
335{
336 switch (len) {
337#ifdef UATOMIC_HAS_ATOMIC_BYTE
338 case 1:
339 __sync_and_and_fetch_1((uint8_t *) addr, val);
340 return;
341#endif
342#ifdef UATOMIC_HAS_ATOMIC_SHORT
343 case 2:
344 __sync_and_and_fetch_2((uint16_t *) addr, val);
345 return;
346#endif
347 case 4:
348 __sync_and_and_fetch_4((uint32_t *) addr, val);
349 return;
350#if (CAA_BITS_PER_LONG == 64)
351 case 8:
352 __sync_and_and_fetch_8((uint64_t *) addr, val);
353 return;
354#endif
355 }
356 _uatomic_link_error();
357}
358
359#define uatomic_and(addr, v) \
360 (_uatomic_and((addr), \
361 caa_cast_long_keep_sign(v), \
362 sizeof(*(addr))))
363#define cmm_smp_mb__before_uatomic_and() cmm_barrier()
364#define cmm_smp_mb__after_uatomic_and() cmm_barrier()
365
366#endif
367
368/* uatomic_or */
369
370#ifndef uatomic_or
371static inline __attribute__((always_inline))
372void _uatomic_or(void *addr, unsigned long val,
373 int len)
374{
375 switch (len) {
376#ifdef UATOMIC_HAS_ATOMIC_BYTE
377 case 1:
378 __sync_or_and_fetch_1((uint8_t *) addr, val);
379 return;
380#endif
381#ifdef UATOMIC_HAS_ATOMIC_SHORT
382 case 2:
383 __sync_or_and_fetch_2((uint16_t *) addr, val);
384 return;
385#endif
386 case 4:
387 __sync_or_and_fetch_4((uint32_t *) addr, val);
388 return;
389#if (CAA_BITS_PER_LONG == 64)
390 case 8:
391 __sync_or_and_fetch_8((uint64_t *) addr, val);
392 return;
393#endif
394 }
395 _uatomic_link_error();
396 return;
397}
398
399#define uatomic_or(addr, v) \
400 (_uatomic_or((addr), \
401 caa_cast_long_keep_sign(v), \
402 sizeof(*(addr))))
403#define cmm_smp_mb__before_uatomic_or() cmm_barrier()
404#define cmm_smp_mb__after_uatomic_or() cmm_barrier()
405
406#endif
407
408
409/* uatomic_add_return */
410
411#ifndef uatomic_add_return
412static inline __attribute__((always_inline))
413unsigned long _uatomic_add_return(void *addr, unsigned long val,
414 int len)
415{
416 switch (len) {
417#ifdef UATOMIC_HAS_ATOMIC_BYTE
418 case 1:
419 return __sync_add_and_fetch_1((uint8_t *) addr, val);
420#endif
421#ifdef UATOMIC_HAS_ATOMIC_SHORT
422 case 2:
423 return __sync_add_and_fetch_2((uint16_t *) addr, val);
424#endif
425 case 4:
426 return __sync_add_and_fetch_4((uint32_t *) addr, val);
427#if (CAA_BITS_PER_LONG == 64)
428 case 8:
429 return __sync_add_and_fetch_8((uint64_t *) addr, val);
430#endif
431 }
432 _uatomic_link_error();
433 return 0;
434}
435
436
437#define uatomic_add_return(addr, v) \
438 ((__typeof__(*(addr))) _uatomic_add_return((addr), \
439 caa_cast_long_keep_sign(v), \
440 sizeof(*(addr))))
441#endif /* #ifndef uatomic_add_return */
442
443#ifndef uatomic_xchg
444/* xchg */
445
446static inline __attribute__((always_inline))
447unsigned long _uatomic_exchange(void *addr, unsigned long val, int len)
448{
449 switch (len) {
450#ifdef UATOMIC_HAS_ATOMIC_BYTE
451 case 1:
452 {
453 uint8_t old;
454
455 do {
456 old = uatomic_read((uint8_t *) addr);
457 } while (!__sync_bool_compare_and_swap_1((uint8_t *) addr,
458 old, val));
459
460 return old;
461 }
462#endif
463#ifdef UATOMIC_HAS_ATOMIC_SHORT
464 case 2:
465 {
466 uint16_t old;
467
468 do {
469 old = uatomic_read((uint16_t *) addr);
470 } while (!__sync_bool_compare_and_swap_2((uint16_t *) addr,
471 old, val));
472
473 return old;
474 }
475#endif
476 case 4:
477 {
478 uint32_t old;
479
480 do {
481 old = uatomic_read((uint32_t *) addr);
482 } while (!__sync_bool_compare_and_swap_4((uint32_t *) addr,
483 old, val));
484
485 return old;
486 }
487#if (CAA_BITS_PER_LONG == 64)
488 case 8:
489 {
490 uint64_t old;
491
492 do {
493 old = uatomic_read((uint64_t *) addr);
494 } while (!__sync_bool_compare_and_swap_8((uint64_t *) addr,
495 old, val));
496
497 return old;
498 }
499#endif
500 }
501 _uatomic_link_error();
502 return 0;
503}
504
505#define uatomic_xchg(addr, v) \
506 ((__typeof__(*(addr))) _uatomic_exchange((addr), \
507 caa_cast_long_keep_sign(v), \
508 sizeof(*(addr))))
509#endif /* #ifndef uatomic_xchg */
510
511#else /* #ifndef uatomic_cmpxchg */
512
513#ifndef uatomic_and
514/* uatomic_and */
515
516static inline __attribute__((always_inline))
517void _uatomic_and(void *addr, unsigned long val, int len)
518{
519 switch (len) {
520#ifdef UATOMIC_HAS_ATOMIC_BYTE
521 case 1:
522 {
523 uint8_t old, oldt;
524
525 oldt = uatomic_read((uint8_t *) addr);
526 do {
527 old = oldt;
528 oldt = _uatomic_cmpxchg(addr, old, old & val, 1);
529 } while (oldt != old);
530
531 return;
532 }
533#endif
534#ifdef UATOMIC_HAS_ATOMIC_SHORT
535 case 2:
536 {
537 uint16_t old, oldt;
538
539 oldt = uatomic_read((uint16_t *) addr);
540 do {
541 old = oldt;
542 oldt = _uatomic_cmpxchg(addr, old, old & val, 2);
543 } while (oldt != old);
544 }
545#endif
546 case 4:
547 {
548 uint32_t old, oldt;
549
550 oldt = uatomic_read((uint32_t *) addr);
551 do {
552 old = oldt;
553 oldt = _uatomic_cmpxchg(addr, old, old & val, 4);
554 } while (oldt != old);
555
556 return;
557 }
558#if (CAA_BITS_PER_LONG == 64)
559 case 8:
560 {
561 uint64_t old, oldt;
562
563 oldt = uatomic_read((uint64_t *) addr);
564 do {
565 old = oldt;
566 oldt = _uatomic_cmpxchg(addr, old, old & val, 8);
567 } while (oldt != old);
568
569 return;
570 }
571#endif
572 }
573 _uatomic_link_error();
574}
575
576#define uatomic_and(addr, v) \
577 (_uatomic_and((addr), \
578 caa_cast_long_keep_sign(v), \
579 sizeof(*(addr))))
580#define cmm_smp_mb__before_uatomic_and() cmm_barrier()
581#define cmm_smp_mb__after_uatomic_and() cmm_barrier()
582
583#endif /* #ifndef uatomic_and */
584
585#ifndef uatomic_or
586/* uatomic_or */
587
588static inline __attribute__((always_inline))
589void _uatomic_or(void *addr, unsigned long val, int len)
590{
591 switch (len) {
592#ifdef UATOMIC_HAS_ATOMIC_BYTE
593 case 1:
594 {
595 uint8_t old, oldt;
596
597 oldt = uatomic_read((uint8_t *) addr);
598 do {
599 old = oldt;
600 oldt = _uatomic_cmpxchg(addr, old, old | val, 1);
601 } while (oldt != old);
602
603 return;
604 }
605#endif
606#ifdef UATOMIC_HAS_ATOMIC_SHORT
607 case 2:
608 {
609 uint16_t old, oldt;
610
611 oldt = uatomic_read((uint16_t *) addr);
612 do {
613 old = oldt;
614 oldt = _uatomic_cmpxchg(addr, old, old | val, 2);
615 } while (oldt != old);
616
617 return;
618 }
619#endif
620 case 4:
621 {
622 uint32_t old, oldt;
623
624 oldt = uatomic_read((uint32_t *) addr);
625 do {
626 old = oldt;
627 oldt = _uatomic_cmpxchg(addr, old, old | val, 4);
628 } while (oldt != old);
629
630 return;
631 }
632#if (CAA_BITS_PER_LONG == 64)
633 case 8:
634 {
635 uint64_t old, oldt;
636
637 oldt = uatomic_read((uint64_t *) addr);
638 do {
639 old = oldt;
640 oldt = _uatomic_cmpxchg(addr, old, old | val, 8);
641 } while (oldt != old);
642
643 return;
644 }
645#endif
646 }
647 _uatomic_link_error();
648}
649
650#define uatomic_or(addr, v) \
651 (_uatomic_or((addr), \
652 caa_cast_long_keep_sign(v), \
653 sizeof(*(addr))))
654#define cmm_smp_mb__before_uatomic_or() cmm_barrier()
655#define cmm_smp_mb__after_uatomic_or() cmm_barrier()
656
657#endif /* #ifndef uatomic_or */
658
659#ifndef uatomic_add_return
660/* uatomic_add_return */
661
662static inline __attribute__((always_inline))
663unsigned long _uatomic_add_return(void *addr, unsigned long val, int len)
664{
665 switch (len) {
666#ifdef UATOMIC_HAS_ATOMIC_BYTE
667 case 1:
668 {
669 uint8_t old, oldt;
670
671 oldt = uatomic_read((uint8_t *) addr);
672 do {
673 old = oldt;
674 oldt = uatomic_cmpxchg((uint8_t *) addr,
675 old, old + val);
676 } while (oldt != old);
677
678 return old + val;
679 }
680#endif
681#ifdef UATOMIC_HAS_ATOMIC_SHORT
682 case 2:
683 {
684 uint16_t old, oldt;
685
686 oldt = uatomic_read((uint16_t *) addr);
687 do {
688 old = oldt;
689 oldt = uatomic_cmpxchg((uint16_t *) addr,
690 old, old + val);
691 } while (oldt != old);
692
693 return old + val;
694 }
695#endif
696 case 4:
697 {
698 uint32_t old, oldt;
699
700 oldt = uatomic_read((uint32_t *) addr);
701 do {
702 old = oldt;
703 oldt = uatomic_cmpxchg((uint32_t *) addr,
704 old, old + val);
705 } while (oldt != old);
706
707 return old + val;
708 }
709#if (CAA_BITS_PER_LONG == 64)
710 case 8:
711 {
712 uint64_t old, oldt;
713
714 oldt = uatomic_read((uint64_t *) addr);
715 do {
716 old = oldt;
717 oldt = uatomic_cmpxchg((uint64_t *) addr,
718 old, old + val);
719 } while (oldt != old);
720
721 return old + val;
722 }
723#endif
724 }
725 _uatomic_link_error();
726 return 0;
727}
728
729#define uatomic_add_return(addr, v) \
730 ((__typeof__(*(addr))) _uatomic_add_return((addr), \
731 caa_cast_long_keep_sign(v), \
732 sizeof(*(addr))))
733#endif /* #ifndef uatomic_add_return */
734
735#ifndef uatomic_xchg
736/* xchg */
737
738static inline __attribute__((always_inline))
739unsigned long _uatomic_exchange(void *addr, unsigned long val, int len)
740{
741 switch (len) {
742#ifdef UATOMIC_HAS_ATOMIC_BYTE
743 case 1:
744 {
745 uint8_t old, oldt;
746
747 oldt = uatomic_read((uint8_t *) addr);
748 do {
749 old = oldt;
750 oldt = uatomic_cmpxchg((uint8_t *) addr,
751 old, val);
752 } while (oldt != old);
753
754 return old;
755 }
756#endif
757#ifdef UATOMIC_HAS_ATOMIC_SHORT
758 case 2:
759 {
760 uint16_t old, oldt;
761
762 oldt = uatomic_read((uint16_t *) addr);
763 do {
764 old = oldt;
765 oldt = uatomic_cmpxchg((uint16_t *) addr,
766 old, val);
767 } while (oldt != old);
768
769 return old;
770 }
771#endif
772 case 4:
773 {
774 uint32_t old, oldt;
775
776 oldt = uatomic_read((uint32_t *) addr);
777 do {
778 old = oldt;
779 oldt = uatomic_cmpxchg((uint32_t *) addr,
780 old, val);
781 } while (oldt != old);
782
783 return old;
784 }
785#if (CAA_BITS_PER_LONG == 64)
786 case 8:
787 {
788 uint64_t old, oldt;
789
790 oldt = uatomic_read((uint64_t *) addr);
791 do {
792 old = oldt;
793 oldt = uatomic_cmpxchg((uint64_t *) addr,
794 old, val);
795 } while (oldt != old);
796
797 return old;
798 }
799#endif
800 }
801 _uatomic_link_error();
802 return 0;
803}
804
805#define uatomic_xchg(addr, v) \
806 ((__typeof__(*(addr))) _uatomic_exchange((addr), \
807 caa_cast_long_keep_sign(v), \
808 sizeof(*(addr))))
809#endif /* #ifndef uatomic_xchg */
810
811#endif /* #else #ifndef uatomic_cmpxchg */
812
813/* uatomic_sub_return, uatomic_add, uatomic_sub, uatomic_inc, uatomic_dec */
814
815#ifndef uatomic_add
816#define uatomic_add(addr, v) (void)uatomic_add_return((addr), (v))
817#define cmm_smp_mb__before_uatomic_add() cmm_barrier()
818#define cmm_smp_mb__after_uatomic_add() cmm_barrier()
819#endif
820
821#define uatomic_sub_return(addr, v) \
822 uatomic_add_return((addr), -(caa_cast_long_keep_sign(v)))
823#define uatomic_sub(addr, v) \
824 uatomic_add((addr), -(caa_cast_long_keep_sign(v)))
825#define cmm_smp_mb__before_uatomic_sub() cmm_smp_mb__before_uatomic_add()
826#define cmm_smp_mb__after_uatomic_sub() cmm_smp_mb__after_uatomic_add()
827
828#ifndef uatomic_inc
829#define uatomic_inc(addr) uatomic_add((addr), 1)
830#define cmm_smp_mb__before_uatomic_inc() cmm_smp_mb__before_uatomic_add()
831#define cmm_smp_mb__after_uatomic_inc() cmm_smp_mb__after_uatomic_add()
832#endif
833
834#ifndef uatomic_dec
835#define uatomic_dec(addr) uatomic_add((addr), -1)
836#define cmm_smp_mb__before_uatomic_dec() cmm_smp_mb__before_uatomic_add()
837#define cmm_smp_mb__after_uatomic_dec() cmm_smp_mb__after_uatomic_add()
838#endif
839
840#ifdef __cplusplus
841}
842#endif
843
844#endif /* _URCU_UATOMIC_GENERIC_H */
This page took 0.024848 seconds and 4 git commands to generate.