P99
p99_atomic_gcc_sync.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_SYNC_H
22 #define P99_ATOMIC_GCC_SYNC_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 
37 #define p00_atomic_exchange_n_(PTR, DES, ORD, ...) \
38 p99_extension ({ \
39  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
40  P99_MACRO_VAR(p00_des, (DES)); \
41  register __typeof__(*(PTR)) p00_ret = p00_des; \
42  for (;;) { \
43  register __typeof__(*(PTR)) p00_val = __sync_val_compare_and_swap(p00_ptr, p00_ret, p00_des); \
44  if (P99_LIKELY(p00_val == p00_ret)) break; \
45  p00_ret = p00_val; \
46  } \
47  p00_ret = p00_ret; \
48  })
49 
50 #define p00_atomic_exchange_n(...) p00_atomic_exchange_n_(__VA_ARGS__,,)
51 
52 #define p00_mfence(...) __sync_synchronize()
53 
54 #define p00_sync_lock_release_(OBJ, ORD, ...) \
55 p99_extension ({ \
56  P99_MACRO_PVAR(p00_obj, (OBJ), volatile); \
57  /* __sync_lock_release only has release consistency */ \
58  /* the fence must come before so nothing can be reordered after */ \
59  switch (ORD) { \
60  case memory_order_consume: ; \
61  case memory_order_acquire: ; \
62  case memory_order_acq_rel: ; \
63  case memory_order_seq_cst: ; \
64  p00_mfence(); \
65  } \
66  __sync_lock_release(p00_obj); \
67  })
68 
69 #define p00_sync_lock_test_and_set_(OBJ, ORD, ...) \
70 p99_extension ({ \
71  P99_MACRO_PVAR(p00_obj, (OBJ), volatile); \
72  /* __sync_lock_test_and_set only has acquire consistency */ \
73  int ret = __sync_lock_test_and_set(p00_obj, 1); \
74  /* the fence must come after so nothing can be reordered before */ \
75  switch (ORD) { \
76  case memory_order_consume: ; \
77  case memory_order_release: ; \
78  case memory_order_acq_rel: ; \
79  case memory_order_seq_cst: ; \
80  p00_mfence(); \
81  } \
82  ret = ret; \
83  })
84 
85 #define p00_sync_lock_release(...) p00_sync_lock_release_(__VA_ARGS__, memory_order_seq_cst, )
86 #define p00_sync_lock_test_and_set(...) p00_sync_lock_test_and_set_(__VA_ARGS__, memory_order_seq_cst, )
87 
88 #define p00_atomic_compare_exchange_n_(PTR, EXP, DES, WEAK, SUC, FAI, ...) \
89 p99_extension ({ \
90  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
91  P99_MACRO_VAR(p00_exp, (EXP)); \
92  P99_MACRO_VAR(p00_des, (DES), const); \
93  __typeof__(*PTR) p00_val = __sync_val_compare_and_swap(p00_ptr, *p00_exp, p00_des); \
94  _Bool p00_ret = (*p00_exp == p00_val); \
95  if (!p00_ret) *p00_exp = p00_val; \
96  p00_ret = p00_ret; \
97  })
98 
99 #define p00_atomic_compare_exchange_n(...) \
100  P99_IF_EQ(P99_NARG(__VA_ARGS__), 3) \
101  (p00_atomic_compare_exchange_n_(__VA_ARGS__, 0, memory_order_seq_cst, memory_order_seq_cst)) \
102  (p00_atomic_compare_exchange_n_(__VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst, ))
103 
104 #define p00_atomic_load_n_(PTR, ORD, ...) \
105 p99_extension ({ \
106  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
107  /* Ensure synchronization with all stores before */ \
108  switch (ORD) { \
109  case memory_order_consume:; \
110  case memory_order_acquire:; \
111  case memory_order_acq_rel:; \
112  (void)__sync_bool_compare_and_swap(p00_ptr, 0, 0); \
113  break; \
114  case memory_order_seq_cst:; \
115  p00_mfence(); \
116  } \
117  /* now ensure the load of the correct value */ \
118  register __typeof__(*(PTR)) const p00_ret = *p00_ptr; \
119  /* Inhibit reordering with all code after */ \
120  P99_MARK("load boundary for " P99_STRINGIFY(PTR)); \
121  p00_ret; \
122  })
123 
124 #define p00_atomic_load_n(...) p00_atomic_load_n_(__VA_ARGS__,,)
125 
126 #define p00_atomic_store_n_(PTR, DES, ORD, ...) \
127 p99_extension ({ \
128  P99_MACRO_PVAR(p00_ptr, (PTR), volatile); \
129  P99_MACRO_VAR(p00_des, (DES), const); \
130  /* Inhibit reordering with all code before */ \
131  P99_MARK("store boundary for " P99_STRINGIFY(PTR)); \
132  /* now ensure the store of the correct value */ \
133  *p00_ptr = p00_des; \
134  /* Ensure that store is visible for all code hereafter */ \
135  switch (ORD) { \
136  case memory_order_consume:; \
137  case memory_order_release:; \
138  case memory_order_acq_rel:; \
139  (void)__sync_bool_compare_and_swap(p00_ptr, p00_des, p00_des); \
140  break; \
141  case memory_order_seq_cst:; \
142  p00_mfence(); \
143  } \
144  })
145 
146 #define p00_atomic_store_n(...) p00_atomic_store_n_(__VA_ARGS__, memory_order_seq_cst,)
147 
148 
149 #define p00_atomic_fetch_add_(PTR, VAL, ORD, ...) __sync_fetch_and_add((PTR), (VAL))
150 #define p00_atomic_fetch_add(...) p00_atomic_fetch_add_(__VA_ARGS__, ,)
151 #define p00_atomic_fetch_and_(PTR, VAL, ORD, ...) __sync_fetch_and_and((PTR), (VAL))
152 #define p00_atomic_fetch_and(...) p00_atomic_fetch_and_(__VA_ARGS__, ,)
153 #define p00_atomic_fetch_or_(PTR, VAL, ORD, ...) __sync_fetch_and_or((PTR), (VAL))
154 #define p00_atomic_fetch_or(...) p00_atomic_fetch_or_(__VA_ARGS__, ,)
155 #define p00_atomic_fetch_sub_(PTR, VAL, ORD, ...) __sync_fetch_and_sub((PTR), (VAL))
156 #define p00_atomic_fetch_sub(...) p00_atomic_fetch_sub_(__VA_ARGS__, ,)
157 #define p00_atomic_fetch_xor_(PTR, VAL, ORD, ...) __sync_fetch_and_xor((PTR), (VAL))
158 #define p00_atomic_fetch_xor(...) p00_atomic_fetch_xor_(__VA_ARGS__, ,)
159 
160 
161 #endif
p99_args.h
Providing macros that handle variadic macro argument lists.