P99
p99_atomic_gcc_atomic.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the author and copyright holder for this work is */
5 /* (C) copyright 2012, 2014 Jens Gustedt, INRIA, France */
6 /* */
7 /* This file is free software; it is part of the P99 project. */
8 /* */
9 /* Licensed under the Apache License, Version 2.0 (the "License"); */
10 /* you may not use this file except in compliance with the License. */
11 /* You may obtain a copy of the License at */
12 /* */
13 /* http://www.apache.org/licenses/LICENSE-2.0 */
14 /* */
15 /* Unless required by applicable law or agreed to in writing, software */
16 /* distributed under the License is distributed on an "AS IS" BASIS, */
17 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
18 /* See the License for the specific language governing permissions and */
19 /* limitations under the License. */
20 /* */
21 #ifndef P99_ATOMIC_GCC_ATOMIC_H
22 #define P99_ATOMIC_GCC_ATOMIC_H 1
23 
24 #ifndef P99_ATOMIC_H
25 # warning "never include this file directly, use p99_atomic.h, instead"
26 #endif
27 
28 #include "p99_args.h"
29 
41 #define p00_atomic_clear(OBJ, ORD) \
42 p99_extension ({ \
43  p00_atomic_flag volatile* p00_obj = (OBJ); \
44  __atomic_clear(p00_obj, (ORD)); \
45  })
46 
47 #define p00_atomic_test_and_set(OBJ, ORD) \
48 p99_extension ({ \
49  p00_atomic_flag volatile* p00_obj = (OBJ); \
50  __atomic_test_and_set(p00_obj, (ORD)); \
51  })
52 
53 #define p00_mfence(...) \
54  P99_IF_EMPTY(__VA_ARGS__) \
55  (__atomic_thread_fence(__ATOMIC_SEQ_CST)) \
56  (__atomic_thread_fence(__VA_ARGS__))
57 
58 #define p00_sync_lock_release(...) \
59  P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
60  (p00_atomic_clear(__VA_ARGS__, __ATOMIC_SEQ_CST)) \
61  (p00_atomic_clear(__VA_ARGS__))
62 
63 #define p00_sync_lock_test_and_set(...) \
64  P99_IF_LT(P99_NARG(__VA_ARGS__), 2) \
65  (p00_atomic_test_and_set(__VA_ARGS__, __ATOMIC_SEQ_CST)) \
66  (p00_atomic_test_and_set(__VA_ARGS__))
67 
68 #define p00_atomic_compare_exchange_n_(PTR, EXP, DES, WEAK, SUC, FAI, ...) \
69 p99_extension ({ \
70  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
71  P99_MACRO_PVAR(p00_exp, (EXP), volatile); \
72  P99_MACRO_VAR(p00_desp, (DES)); \
73  __typeof__(*(PTR)) p00_des = p00_desp; \
74  __atomic_compare_exchange_n(p00_ptr, (void*)p00_exp, p00_des, (WEAK), (SUC), (FAI)); \
75  })
76 
77 #define p00_atomic_compare_exchange_n(...) \
78  P99_IF_EQ(P99_NARG(__VA_ARGS__), 3) \
79  (p00_atomic_compare_exchange_n_(__VA_ARGS__, 0, memory_order_seq_cst, memory_order_seq_cst)) \
80  (p00_atomic_compare_exchange_n_(__VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst, ))
81 
82 #define p00_atomic_exchange_n_(PTR, DES, ORD, ...) \
83 p99_extension ({ \
84  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
85  P99_MACRO_VAR(p00_des, (DES)); \
86  P99_MACRO_VAR(p00_ord, (ORD), const); \
87  __typeof__(*p00_ptr) p00_ret; \
88  switch (p00_ord) { \
89  case __ATOMIC_RELAXED:; \
90  p00_ret = __atomic_exchange_n(p00_ptr, p00_des, __ATOMIC_RELAXED); \
91  break; \
92  case __ATOMIC_ACQUIRE:; \
93  p00_ret = __atomic_exchange_n(p00_ptr, p00_des, __ATOMIC_ACQUIRE); \
94  break; \
95  case __ATOMIC_RELEASE:; \
96  p00_ret = __atomic_exchange_n(p00_ptr, p00_des, __ATOMIC_RELEASE); \
97  break; \
98  case __ATOMIC_ACQ_REL:; \
99  p00_ret = __atomic_exchange_n(p00_ptr, p00_des, __ATOMIC_ACQ_REL); \
100  break; \
101  default: \
102  p00_ret = __atomic_exchange_n(p00_ptr, p00_des, __ATOMIC_SEQ_CST); \
103  } \
104  p00_ret = p00_ret; \
105  })
106 
107 #define p00_atomic_exchange_n(...) p00_atomic_exchange_n_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
108 
109 #define p00_atomic_load_n_(PTR, ORD, ...) \
110 p99_extension ({ \
111  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
112  P99_MACRO_VAR(p00_ord, (ORD), const); \
113  __typeof__(*p00_ptr) p00_ret; \
114  switch (p00_ord) { \
115  case __ATOMIC_RELAXED:; \
116  p00_ret = __atomic_load_n(p00_ptr, __ATOMIC_RELAXED); \
117  break; \
118  case __ATOMIC_ACQUIRE:; \
119  p00_ret = __atomic_load_n(p00_ptr, __ATOMIC_ACQUIRE); \
120  break; \
121  case __ATOMIC_CONSUME:; \
122  p00_ret = __atomic_load_n(p00_ptr, __ATOMIC_CONSUME); \
123  break; \
124  default: \
125  p00_ret =__atomic_load_n(p00_ptr, __ATOMIC_SEQ_CST); \
126  } \
127  p00_ret = p00_ret; \
128  })
129 
130 #define p00_atomic_load_n(...) p00_atomic_load_n_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
131 
132 #define p00_atomic_store_n_(PTR, DES, ORD, ...) \
133 p99_extension ({ \
134  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
135  P99_MACRO_VAR(p00_des, (DES)); \
136  P99_MACRO_VAR(p00_ord, (ORD), const); \
137  switch (p00_ord) { \
138  case __ATOMIC_RELAXED:; \
139  __atomic_store_n(p00_ptr, p00_des, __ATOMIC_RELAXED); \
140  break; \
141  case __ATOMIC_RELEASE:; \
142  __atomic_store_n(p00_ptr, p00_des, __ATOMIC_RELEASE); \
143  break; \
144  default: \
145  __atomic_store_n(p00_ptr, p00_des, __ATOMIC_SEQ_CST); \
146  } \
147  })
148 
149 #define p00_atomic_store_n(...) p00_atomic_store_n_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
150 
151 #define p00_atomic_fetch_add_(PTR, VAL, ORD, ...) __atomic_fetch_add((PTR), (VAL), (ORD))
152 #define p00_atomic_fetch_add(...) p00_atomic_fetch_add_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
153 #define p00_atomic_fetch_and_(PTR, VAL, ORD, ...) __atomic_fetch_and((PTR), (VAL), (ORD))
154 #define p00_atomic_fetch_and(...) p00_atomic_fetch_and_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
155 #define p00_atomic_fetch_or_(PTR, VAL, ORD, ...) __atomic_fetch_or((PTR), (VAL), (ORD))
156 #define p00_atomic_fetch_or(...) p00_atomic_fetch_or_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
157 #define p00_atomic_fetch_sub_(PTR, VAL, ORD, ...) __atomic_fetch_sub((PTR), (VAL), (ORD))
158 #define p00_atomic_fetch_sub(...) p00_atomic_fetch_sub_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
159 #define p00_atomic_fetch_xor_(PTR, VAL, ORD, ...) __atomic_fetch_xor((PTR), (VAL), (ORD))
160 #define p00_atomic_fetch_xor(...) p00_atomic_fetch_xor_(__VA_ARGS__, __ATOMIC_SEQ_CST,)
161 
162 #endif
p99_args.h
Providing macros that handle variadic macro argument lists.