1 /*
2  * Copyright (c) 2003-2011 Hewlett-Packard Development Company, L.P.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 
23 /*
24  * Generalize atomic operations for atomic_ops.h.
25  * Should not be included directly.
26  *
27  * We make no attempt to define useless operations, such as
28  * AO_nop_acquire
29  * AO_nop_release
30  *
31  * We have also so far neglected to define some others, which
32  * do not appear likely to be useful, e.g. stores with acquire
33  * or read barriers.
34  *
35  * This file is sometimes included twice by atomic_ops.h.
36  * All definitions include explicit checks that we are not replacing
37  * an earlier definition.  In general, more desirable expansions
38  * appear earlier so that we are more likely to use them.
39  *
40  * We only make safe generalizations, except that by default we define
41  * the ...dd_acquire_read operations to be equivalent to those without
42  * a barrier.  On platforms for which this is unsafe, the platform-specific
43  * file must define AO_NO_DD_ORDERING.
44  */
45 
46 #ifndef AO_ATOMIC_OPS_H
47 # error This file should not be included directly.
48 #endif
49 
50 /* Generate test_and_set_full, if necessary and possible.       */
51 #if !defined(AO_HAVE_test_and_set) && !defined(AO_HAVE_test_and_set_release) \
52     && !defined(AO_HAVE_test_and_set_acquire) \
53     && !defined(AO_HAVE_test_and_set_read) \
54     && !defined(AO_HAVE_test_and_set_full)
55 
56   /* Emulate AO_compare_and_swap() via AO_fetch_compare_and_swap().     */
57 # if defined(AO_HAVE_fetch_compare_and_swap) \
58      && !defined(AO_HAVE_compare_and_swap)
59     AO_INLINE int
AO_compare_and_swap(volatile AO_t * addr,AO_t old_val,AO_t new_val)60     AO_compare_and_swap(volatile AO_t *addr, AO_t old_val, AO_t new_val)
61     {
62       return AO_fetch_compare_and_swap(addr, old_val, new_val) == old_val;
63     }
64 #   define AO_HAVE_compare_and_swap
65 # endif
66 
67 # if defined(AO_HAVE_fetch_compare_and_swap_full) \
68      && !defined(AO_HAVE_compare_and_swap_full)
69     AO_INLINE int
AO_compare_and_swap_full(volatile AO_t * addr,AO_t old_val,AO_t new_val)70     AO_compare_and_swap_full(volatile AO_t *addr, AO_t old_val, AO_t new_val)
71     {
72       return AO_fetch_compare_and_swap_full(addr, old_val, new_val)
73                == old_val;
74     }
75 #   define AO_HAVE_compare_and_swap_full
76 # endif
77 
78 # if defined(AO_HAVE_fetch_compare_and_swap_acquire) \
79      && !defined(AO_HAVE_compare_and_swap_acquire)
80     AO_INLINE int
AO_compare_and_swap_acquire(volatile AO_t * addr,AO_t old_val,AO_t new_val)81     AO_compare_and_swap_acquire(volatile AO_t *addr, AO_t old_val,
82                                 AO_t new_val)
83     {
84       return AO_fetch_compare_and_swap_acquire(addr, old_val, new_val)
85                == old_val;
86     }
87 #   define AO_HAVE_compare_and_swap_acquire
88 # endif
89 
90 # if defined(AO_HAVE_fetch_compare_and_swap_release) \
91      && !defined(AO_HAVE_compare_and_swap_release)
92     AO_INLINE int
AO_compare_and_swap_release(volatile AO_t * addr,AO_t old_val,AO_t new_val)93     AO_compare_and_swap_release(volatile AO_t *addr, AO_t old_val,
94                                 AO_t new_val)
95     {
96       return AO_fetch_compare_and_swap_release(addr, old_val, new_val)
97                == old_val;
98     }
99 #   define AO_HAVE_compare_and_swap_release
100 # endif
101 
102 # if defined(AO_CHAR_TS_T)
103 #   define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) \
104                                 AO_char_compare_and_swap_full(a,o,n)
105 #   define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \
106                                 AO_char_compare_and_swap_acquire(a,o,n)
107 #   define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \
108                                 AO_char_compare_and_swap_release(a,o,n)
109 #   define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_char_compare_and_swap(a,o,n)
110 # endif
111 
112 # if defined(AO_AO_TS_T)
113 #   define AO_TS_COMPARE_AND_SWAP_FULL(a,o,n) AO_compare_and_swap_full(a,o,n)
114 #   define AO_TS_COMPARE_AND_SWAP_ACQUIRE(a,o,n) \
115                                 AO_compare_and_swap_acquire(a,o,n)
116 #   define AO_TS_COMPARE_AND_SWAP_RELEASE(a,o,n) \
117                                 AO_compare_and_swap_release(a,o,n)
118 #   define AO_TS_COMPARE_AND_SWAP(a,o,n) AO_compare_and_swap(a,o,n)
119 # endif
120 
121 # if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap_full)) \
122      || (defined(AO_CHAR_TS_T) && defined(AO_HAVE_char_compare_and_swap_full))
123     AO_INLINE AO_TS_VAL_t
AO_test_and_set_full(volatile AO_TS_t * addr)124     AO_test_and_set_full(volatile AO_TS_t *addr)
125     {
126       if (AO_TS_COMPARE_AND_SWAP_FULL(addr, AO_TS_CLEAR, AO_TS_SET))
127         return AO_TS_CLEAR;
128       else
129         return AO_TS_SET;
130     }
131 #   define AO_HAVE_test_and_set_full
132 # endif /* AO_HAVE_compare_and_swap_full */
133 
134 # if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap_acquire)) \
135      || (defined(AO_CHAR_TS_T) \
136          && defined(AO_HAVE_char_compare_and_swap_acquire))
137     AO_INLINE AO_TS_VAL_t
AO_test_and_set_acquire(volatile AO_TS_t * addr)138     AO_test_and_set_acquire(volatile AO_TS_t *addr)
139     {
140       if (AO_TS_COMPARE_AND_SWAP_ACQUIRE(addr, AO_TS_CLEAR, AO_TS_SET))
141         return AO_TS_CLEAR;
142       else
143         return AO_TS_SET;
144     }
145 #   define AO_HAVE_test_and_set_acquire
146 # endif /* AO_HAVE_compare_and_swap_acquire */
147 
148 # if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap_release)) \
149      || (defined(AO_CHAR_TS_T) \
150          && defined(AO_HAVE_char_compare_and_swap_release))
151     AO_INLINE AO_TS_VAL_t
AO_test_and_set_release(volatile AO_TS_t * addr)152     AO_test_and_set_release(volatile AO_TS_t *addr)
153     {
154       if (AO_TS_COMPARE_AND_SWAP_RELEASE(addr, AO_TS_CLEAR, AO_TS_SET))
155         return AO_TS_CLEAR;
156       else
157         return AO_TS_SET;
158     }
159 #   define AO_HAVE_test_and_set_release
160 # endif /* AO_HAVE_compare_and_swap_release */
161 
162 # if (defined(AO_AO_TS_T) && defined(AO_HAVE_compare_and_swap)) \
163      || (defined(AO_CHAR_TS_T) && defined(AO_HAVE_char_compare_and_swap))
164     AO_INLINE AO_TS_VAL_t
AO_test_and_set(volatile AO_TS_t * addr)165     AO_test_and_set(volatile AO_TS_t *addr)
166     {
167       if (AO_TS_COMPARE_AND_SWAP(addr, AO_TS_CLEAR, AO_TS_SET))
168         return AO_TS_CLEAR;
169       else
170         return AO_TS_SET;
171     }
172 #   define AO_HAVE_test_and_set
173 # endif /* AO_HAVE_compare_and_swap */
174 #endif /* No prior test and set */
175 
176 /* Nop */
177 #if !defined(AO_HAVE_nop)
AO_nop(void)178   AO_INLINE void AO_nop(void) {}
179 # define AO_HAVE_nop
180 #endif
181 
182 #if defined(AO_HAVE_test_and_set_full) && !defined(AO_HAVE_nop_full)
183   AO_INLINE void
AO_nop_full(void)184   AO_nop_full(void)
185   {
186     AO_TS_t dummy = AO_TS_INITIALIZER;
187     AO_test_and_set_full(&dummy);
188   }
189 # define AO_HAVE_nop_full
190 #endif
191 
192 #if defined(AO_HAVE_nop_acquire) && !defined(CPPCHECK)
193 # error AO_nop_acquire is useless: do not define.
194 #endif
195 
196 #if defined(AO_HAVE_nop_release) && !defined(CPPCHECK)
197 # error AO_nop_release is useless: do not define.
198 #endif
199 
200 #if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_read)
201 # define AO_nop_read() AO_nop_full()
202 # define AO_HAVE_nop_read
203 #endif
204 
205 #if defined(AO_HAVE_nop_full) && !defined(AO_HAVE_nop_write)
206 # define AO_nop_write() AO_nop_full()
207 # define AO_HAVE_nop_write
208 #endif
209 
210 /* Test_and_set */
211 #if defined(AO_HAVE_test_and_set) && defined(AO_HAVE_nop_full) \
212     && !defined(AO_HAVE_test_and_set_release)
213 # define AO_test_and_set_release(addr) (AO_nop_full(), AO_test_and_set(addr))
214 # define AO_HAVE_test_and_set_release
215 #endif
216 
217 #if defined(AO_HAVE_test_and_set) && defined(AO_HAVE_nop_full) \
218     && !defined(AO_HAVE_test_and_set_acquire)
219   AO_INLINE AO_TS_VAL_t
AO_test_and_set_acquire(volatile AO_TS_t * addr)220   AO_test_and_set_acquire(volatile AO_TS_t *addr)
221   {
222     AO_TS_VAL_t result = AO_test_and_set(addr);
223     AO_nop_full();
224     return result;
225   }
226 # define AO_HAVE_test_and_set_acquire
227 #endif
228 
229 #if defined(AO_HAVE_test_and_set_full)
230 # if !defined(AO_HAVE_test_and_set_release)
231 #   define AO_test_and_set_release(addr) AO_test_and_set_full(addr)
232 #   define AO_HAVE_test_and_set_release
233 # endif
234 # if !defined(AO_HAVE_test_and_set_acquire)
235 #   define AO_test_and_set_acquire(addr) AO_test_and_set_full(addr)
236 #   define AO_HAVE_test_and_set_acquire
237 # endif
238 # if !defined(AO_HAVE_test_and_set_write)
239 #   define AO_test_and_set_write(addr) AO_test_and_set_full(addr)
240 #   define AO_HAVE_test_and_set_write
241 # endif
242 # if !defined(AO_HAVE_test_and_set_read)
243 #   define AO_test_and_set_read(addr) AO_test_and_set_full(addr)
244 #   define AO_HAVE_test_and_set_read
245 # endif
246 #endif /* AO_HAVE_test_and_set_full */
247 
248 #if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_release)
249 # define AO_test_and_set(addr) AO_test_and_set_release(addr)
250 # define AO_HAVE_test_and_set
251 #endif
252 #if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_acquire)
253 # define AO_test_and_set(addr) AO_test_and_set_acquire(addr)
254 # define AO_HAVE_test_and_set
255 #endif
256 #if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_write)
257 # define AO_test_and_set(addr) AO_test_and_set_write(addr)
258 # define AO_HAVE_test_and_set
259 #endif
260 #if !defined(AO_HAVE_test_and_set) && defined(AO_HAVE_test_and_set_read)
261 # define AO_test_and_set(addr) AO_test_and_set_read(addr)
262 # define AO_HAVE_test_and_set
263 #endif
264 
265 #if defined(AO_HAVE_test_and_set_acquire) && defined(AO_HAVE_nop_full) \
266     && !defined(AO_HAVE_test_and_set_full)
267 # define AO_test_and_set_full(addr) \
268                         (AO_nop_full(), AO_test_and_set_acquire(addr))
269 # define AO_HAVE_test_and_set_full
270 #endif
271 
272 #if !defined(AO_HAVE_test_and_set_release_write) \
273     && defined(AO_HAVE_test_and_set_write)
274 # define AO_test_and_set_release_write(addr) AO_test_and_set_write(addr)
275 # define AO_HAVE_test_and_set_release_write
276 #endif
277 #if !defined(AO_HAVE_test_and_set_release_write) \
278     && defined(AO_HAVE_test_and_set_release)
279 # define AO_test_and_set_release_write(addr) AO_test_and_set_release(addr)
280 # define AO_HAVE_test_and_set_release_write
281 #endif
282 #if !defined(AO_HAVE_test_and_set_acquire_read) \
283     && defined(AO_HAVE_test_and_set_read)
284 # define AO_test_and_set_acquire_read(addr) AO_test_and_set_read(addr)
285 # define AO_HAVE_test_and_set_acquire_read
286 #endif
287 #if !defined(AO_HAVE_test_and_set_acquire_read) \
288     && defined(AO_HAVE_test_and_set_acquire)
289 # define AO_test_and_set_acquire_read(addr) AO_test_and_set_acquire(addr)
290 # define AO_HAVE_test_and_set_acquire_read
291 #endif
292 
293 #ifdef AO_NO_DD_ORDERING
294 # if defined(AO_HAVE_test_and_set_acquire_read)
295 #   define AO_test_and_set_dd_acquire_read(addr) \
296                                         AO_test_and_set_acquire_read(addr)
297 #   define AO_HAVE_test_and_set_dd_acquire_read
298 # endif
299 #else
300 # if defined(AO_HAVE_test_and_set)
301 #   define AO_test_and_set_dd_acquire_read(addr) AO_test_and_set(addr)
302 #   define AO_HAVE_test_and_set_dd_acquire_read
303 # endif
304 #endif /* !AO_NO_DD_ORDERING */
305 
306 #include "generalize-small.h"
307 
308 #include "generalize-arithm.h"
309 
310 /* Compare_double_and_swap_double based on double_compare_and_swap.     */
311 #ifdef AO_HAVE_DOUBLE_PTR_STORAGE
312 # if defined(AO_HAVE_double_compare_and_swap) \
313      && !defined(AO_HAVE_compare_double_and_swap_double)
314    AO_INLINE int
AO_compare_double_and_swap_double(volatile AO_double_t * addr,AO_t old_val1,AO_t old_val2,AO_t new_val1,AO_t new_val2)315    AO_compare_double_and_swap_double(volatile AO_double_t *addr,
316                                      AO_t old_val1, AO_t old_val2,
317                                      AO_t new_val1, AO_t new_val2)
318    {
319      AO_double_t old_w;
320      AO_double_t new_w;
321      old_w.AO_val1 = old_val1;
322      old_w.AO_val2 = old_val2;
323      new_w.AO_val1 = new_val1;
324      new_w.AO_val2 = new_val2;
325      return AO_double_compare_and_swap(addr, old_w, new_w);
326    }
327 #  define AO_HAVE_compare_double_and_swap_double
328 # endif
329 # if defined(AO_HAVE_double_compare_and_swap_acquire) \
330      && !defined(AO_HAVE_compare_double_and_swap_double_acquire)
331     AO_INLINE int
AO_compare_double_and_swap_double_acquire(volatile AO_double_t * addr,AO_t old_val1,AO_t old_val2,AO_t new_val1,AO_t new_val2)332     AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr,
333                                               AO_t old_val1, AO_t old_val2,
334                                               AO_t new_val1, AO_t new_val2)
335     {
336       AO_double_t old_w;
337       AO_double_t new_w;
338       old_w.AO_val1 = old_val1;
339       old_w.AO_val2 = old_val2;
340       new_w.AO_val1 = new_val1;
341       new_w.AO_val2 = new_val2;
342       return AO_double_compare_and_swap_acquire(addr, old_w, new_w);
343     }
344 #   define AO_HAVE_compare_double_and_swap_double_acquire
345 # endif
346 # if defined(AO_HAVE_double_compare_and_swap_release) \
347      && !defined(AO_HAVE_compare_double_and_swap_double_release)
348     AO_INLINE int
AO_compare_double_and_swap_double_release(volatile AO_double_t * addr,AO_t old_val1,AO_t old_val2,AO_t new_val1,AO_t new_val2)349     AO_compare_double_and_swap_double_release(volatile AO_double_t *addr,
350                                               AO_t old_val1, AO_t old_val2,
351                                               AO_t new_val1, AO_t new_val2)
352     {
353       AO_double_t old_w;
354       AO_double_t new_w;
355       old_w.AO_val1 = old_val1;
356       old_w.AO_val2 = old_val2;
357       new_w.AO_val1 = new_val1;
358       new_w.AO_val2 = new_val2;
359       return AO_double_compare_and_swap_release(addr, old_w, new_w);
360     }
361 #   define AO_HAVE_compare_double_and_swap_double_release
362 # endif
363 # if defined(AO_HAVE_double_compare_and_swap_full) \
364      && !defined(AO_HAVE_compare_double_and_swap_double_full)
365     AO_INLINE int
AO_compare_double_and_swap_double_full(volatile AO_double_t * addr,AO_t old_val1,AO_t old_val2,AO_t new_val1,AO_t new_val2)366     AO_compare_double_and_swap_double_full(volatile AO_double_t *addr,
367                                            AO_t old_val1, AO_t old_val2,
368                                            AO_t new_val1, AO_t new_val2)
369     {
370       AO_double_t old_w;
371       AO_double_t new_w;
372       old_w.AO_val1 = old_val1;
373       old_w.AO_val2 = old_val2;
374       new_w.AO_val1 = new_val1;
375       new_w.AO_val2 = new_val2;
376       return AO_double_compare_and_swap_full(addr, old_w, new_w);
377     }
378 #   define AO_HAVE_compare_double_and_swap_double_full
379 # endif
380 #endif /* AO_HAVE_DOUBLE_PTR_STORAGE */
381 
382 /* Compare_double_and_swap_double */
383 #if defined(AO_HAVE_compare_double_and_swap_double) \
384     && defined(AO_HAVE_nop_full) \
385     && !defined(AO_HAVE_compare_double_and_swap_double_acquire)
386   AO_INLINE int
AO_compare_double_and_swap_double_acquire(volatile AO_double_t * addr,AO_t o1,AO_t o2,AO_t n1,AO_t n2)387   AO_compare_double_and_swap_double_acquire(volatile AO_double_t *addr,
388                                             AO_t o1, AO_t o2,
389                                             AO_t n1, AO_t n2)
390   {
391     int result = AO_compare_double_and_swap_double(addr, o1, o2, n1, n2);
392     AO_nop_full();
393     return result;
394   }
395 # define AO_HAVE_compare_double_and_swap_double_acquire
396 #endif
397 #if defined(AO_HAVE_compare_double_and_swap_double) \
398     && defined(AO_HAVE_nop_full) \
399     && !defined(AO_HAVE_compare_double_and_swap_double_release)
400 # define AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2) \
401       (AO_nop_full(), AO_compare_double_and_swap_double(addr,o1,o2,n1,n2))
402 # define AO_HAVE_compare_double_and_swap_double_release
403 #endif
404 #if defined(AO_HAVE_compare_double_and_swap_double_full)
405 # if !defined(AO_HAVE_compare_double_and_swap_double_release)
406 #   define AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2) \
407                 AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)
408 #   define AO_HAVE_compare_double_and_swap_double_release
409 # endif
410 # if !defined(AO_HAVE_compare_double_and_swap_double_acquire)
411 #   define AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2) \
412                 AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)
413 #   define AO_HAVE_compare_double_and_swap_double_acquire
414 # endif
415 # if !defined(AO_HAVE_compare_double_and_swap_double_write)
416 #   define AO_compare_double_and_swap_double_write(addr,o1,o2,n1,n2) \
417                 AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)
418 #   define AO_HAVE_compare_double_and_swap_double_write
419 # endif
420 # if !defined(AO_HAVE_compare_double_and_swap_double_read)
421 #   define AO_compare_double_and_swap_double_read(addr,o1,o2,n1,n2) \
422                 AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2)
423 #   define AO_HAVE_compare_double_and_swap_double_read
424 # endif
425 #endif /* AO_HAVE_compare_double_and_swap_double_full */
426 
427 #if !defined(AO_HAVE_compare_double_and_swap_double) \
428     && defined(AO_HAVE_compare_double_and_swap_double_release)
429 # define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \
430                 AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2)
431 # define AO_HAVE_compare_double_and_swap_double
432 #endif
433 #if !defined(AO_HAVE_compare_double_and_swap_double) \
434     && defined(AO_HAVE_compare_double_and_swap_double_acquire)
435 # define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \
436                 AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2)
437 # define AO_HAVE_compare_double_and_swap_double
438 #endif
439 #if !defined(AO_HAVE_compare_double_and_swap_double) \
440     && defined(AO_HAVE_compare_double_and_swap_double_write)
441 # define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \
442                 AO_compare_double_and_swap_double_write(addr,o1,o2,n1,n2)
443 # define AO_HAVE_compare_double_and_swap_double
444 #endif
445 #if !defined(AO_HAVE_compare_double_and_swap_double) \
446     && defined(AO_HAVE_compare_double_and_swap_double_read)
447 # define AO_compare_double_and_swap_double(addr,o1,o2,n1,n2) \
448                 AO_compare_double_and_swap_double_read(addr,o1,o2,n1,n2)
449 # define AO_HAVE_compare_double_and_swap_double
450 #endif
451 
452 #if defined(AO_HAVE_compare_double_and_swap_double_acquire) \
453     && defined(AO_HAVE_nop_full) \
454     && !defined(AO_HAVE_compare_double_and_swap_double_full)
455 # define AO_compare_double_and_swap_double_full(addr,o1,o2,n1,n2) \
456                 (AO_nop_full(), \
457                  AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2))
458 # define AO_HAVE_compare_double_and_swap_double_full
459 #endif
460 
461 #if !defined(AO_HAVE_compare_double_and_swap_double_release_write) \
462     && defined(AO_HAVE_compare_double_and_swap_double_write)
463 # define AO_compare_double_and_swap_double_release_write(addr,o1,o2,n1,n2) \
464                 AO_compare_double_and_swap_double_write(addr,o1,o2,n1,n2)
465 # define AO_HAVE_compare_double_and_swap_double_release_write
466 #endif
467 #if !defined(AO_HAVE_compare_double_and_swap_double_release_write) \
468     && defined(AO_HAVE_compare_double_and_swap_double_release)
469 # define AO_compare_double_and_swap_double_release_write(addr,o1,o2,n1,n2) \
470                 AO_compare_double_and_swap_double_release(addr,o1,o2,n1,n2)
471 # define AO_HAVE_compare_double_and_swap_double_release_write
472 #endif
473 #if !defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \
474     && defined(AO_HAVE_compare_double_and_swap_double_read)
475 # define AO_compare_double_and_swap_double_acquire_read(addr,o1,o2,n1,n2) \
476                 AO_compare_double_and_swap_double_read(addr,o1,o2,n1,n2)
477 # define AO_HAVE_compare_double_and_swap_double_acquire_read
478 #endif
479 #if !defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \
480     && defined(AO_HAVE_compare_double_and_swap_double_acquire)
481 # define AO_compare_double_and_swap_double_acquire_read(addr,o1,o2,n1,n2) \
482                 AO_compare_double_and_swap_double_acquire(addr,o1,o2,n1,n2)
483 # define AO_HAVE_compare_double_and_swap_double_acquire_read
484 #endif
485 
486 #ifdef AO_NO_DD_ORDERING
487 # if defined(AO_HAVE_compare_double_and_swap_double_acquire_read)
488 #   define AO_compare_double_and_swap_double_dd_acquire_read(addr,o1,o2,n1,n2) \
489              AO_compare_double_and_swap_double_acquire_read(addr,o1,o2,n1,n2)
490 #   define AO_HAVE_compare_double_and_swap_double_dd_acquire_read
491 # endif
492 #else
493 # if defined(AO_HAVE_compare_double_and_swap_double)
494 #   define AO_compare_double_and_swap_double_dd_acquire_read(addr,o1,o2,n1,n2) \
495                         AO_compare_double_and_swap_double(addr,o1,o2,n1,n2)
496 #   define AO_HAVE_compare_double_and_swap_double_dd_acquire_read
497 # endif
498 #endif /* !AO_NO_DD_ORDERING */
499 
500 /* Compare_and_swap_double */
501 #if defined(AO_HAVE_compare_and_swap_double) && defined(AO_HAVE_nop_full) \
502     && !defined(AO_HAVE_compare_and_swap_double_acquire)
503   AO_INLINE int
AO_compare_and_swap_double_acquire(volatile AO_double_t * addr,AO_t o1,AO_t n1,AO_t n2)504   AO_compare_and_swap_double_acquire(volatile AO_double_t *addr,
505                                             AO_t o1,
506                                             AO_t n1, AO_t n2)
507   {
508     int result = AO_compare_and_swap_double(addr, o1, n1, n2);
509     AO_nop_full();
510     return result;
511   }
512 # define AO_HAVE_compare_and_swap_double_acquire
513 #endif
514 #if defined(AO_HAVE_compare_and_swap_double) \
515     && defined(AO_HAVE_nop_full) \
516     && !defined(AO_HAVE_compare_and_swap_double_release)
517 # define AO_compare_and_swap_double_release(addr,o1,n1,n2) \
518                 (AO_nop_full(), AO_compare_and_swap_double(addr,o1,n1,n2))
519 # define AO_HAVE_compare_and_swap_double_release
520 #endif
521 #if defined(AO_HAVE_compare_and_swap_double_full)
522 # if !defined(AO_HAVE_compare_and_swap_double_release)
523 #   define AO_compare_and_swap_double_release(addr,o1,n1,n2) \
524                                 AO_compare_and_swap_double_full(addr,o1,n1,n2)
525 #   define AO_HAVE_compare_and_swap_double_release
526 # endif
527 # if !defined(AO_HAVE_compare_and_swap_double_acquire)
528 #   define AO_compare_and_swap_double_acquire(addr,o1,n1,n2) \
529                                 AO_compare_and_swap_double_full(addr,o1,n1,n2)
530 #   define AO_HAVE_compare_and_swap_double_acquire
531 # endif
532 # if !defined(AO_HAVE_compare_and_swap_double_write)
533 #   define AO_compare_and_swap_double_write(addr,o1,n1,n2) \
534                                 AO_compare_and_swap_double_full(addr,o1,n1,n2)
535 #   define AO_HAVE_compare_and_swap_double_write
536 # endif
537 # if !defined(AO_HAVE_compare_and_swap_double_read)
538 #   define AO_compare_and_swap_double_read(addr,o1,n1,n2) \
539                                 AO_compare_and_swap_double_full(addr,o1,n1,n2)
540 #   define AO_HAVE_compare_and_swap_double_read
541 # endif
542 #endif /* AO_HAVE_compare_and_swap_double_full */
543 
544 #if !defined(AO_HAVE_compare_and_swap_double) \
545     && defined(AO_HAVE_compare_and_swap_double_release)
546 # define AO_compare_and_swap_double(addr,o1,n1,n2) \
547                         AO_compare_and_swap_double_release(addr,o1,n1,n2)
548 # define AO_HAVE_compare_and_swap_double
549 #endif
550 #if !defined(AO_HAVE_compare_and_swap_double) \
551     && defined(AO_HAVE_compare_and_swap_double_acquire)
552 # define AO_compare_and_swap_double(addr,o1,n1,n2) \
553                         AO_compare_and_swap_double_acquire(addr,o1,n1,n2)
554 # define AO_HAVE_compare_and_swap_double
555 #endif
556 #if !defined(AO_HAVE_compare_and_swap_double) \
557     && defined(AO_HAVE_compare_and_swap_double_write)
558 # define AO_compare_and_swap_double(addr,o1,n1,n2) \
559                         AO_compare_and_swap_double_write(addr,o1,n1,n2)
560 # define AO_HAVE_compare_and_swap_double
561 #endif
562 #if !defined(AO_HAVE_compare_and_swap_double) \
563     && defined(AO_HAVE_compare_and_swap_double_read)
564 # define AO_compare_and_swap_double(addr,o1,n1,n2) \
565                         AO_compare_and_swap_double_read(addr,o1,n1,n2)
566 # define AO_HAVE_compare_and_swap_double
567 #endif
568 
569 #if defined(AO_HAVE_compare_and_swap_double_acquire) \
570     && defined(AO_HAVE_nop_full) \
571     && !defined(AO_HAVE_compare_and_swap_double_full)
572 # define AO_compare_and_swap_double_full(addr,o1,n1,n2) \
573         (AO_nop_full(), AO_compare_and_swap_double_acquire(addr,o1,n1,n2))
574 # define AO_HAVE_compare_and_swap_double_full
575 #endif
576 
577 #if !defined(AO_HAVE_compare_and_swap_double_release_write) \
578     && defined(AO_HAVE_compare_and_swap_double_write)
579 # define AO_compare_and_swap_double_release_write(addr,o1,n1,n2) \
580                         AO_compare_and_swap_double_write(addr,o1,n1,n2)
581 # define AO_HAVE_compare_and_swap_double_release_write
582 #endif
583 #if !defined(AO_HAVE_compare_and_swap_double_release_write) \
584     && defined(AO_HAVE_compare_and_swap_double_release)
585 # define AO_compare_and_swap_double_release_write(addr,o1,n1,n2) \
586                         AO_compare_and_swap_double_release(addr,o1,n1,n2)
587 # define AO_HAVE_compare_and_swap_double_release_write
588 #endif
589 #if !defined(AO_HAVE_compare_and_swap_double_acquire_read) \
590     && defined(AO_HAVE_compare_and_swap_double_read)
591 # define AO_compare_and_swap_double_acquire_read(addr,o1,n1,n2) \
592                         AO_compare_and_swap_double_read(addr,o1,n1,n2)
593 # define AO_HAVE_compare_and_swap_double_acquire_read
594 #endif
595 #if !defined(AO_HAVE_compare_and_swap_double_acquire_read) \
596     && defined(AO_HAVE_compare_and_swap_double_acquire)
597 # define AO_compare_and_swap_double_acquire_read(addr,o1,n1,n2) \
598                         AO_compare_and_swap_double_acquire(addr,o1,n1,n2)
599 # define AO_HAVE_compare_and_swap_double_acquire_read
600 #endif
601 
602 #ifdef AO_NO_DD_ORDERING
603 # if defined(AO_HAVE_compare_and_swap_double_acquire_read)
604 #   define AO_compare_and_swap_double_dd_acquire_read(addr,o1,n1,n2) \
605                         AO_compare_and_swap_double_acquire_read(addr,o1,n1,n2)
606 #   define AO_HAVE_compare_and_swap_double_dd_acquire_read
607 # endif
608 #else
609 # if defined(AO_HAVE_compare_and_swap_double)
610 #   define AO_compare_and_swap_double_dd_acquire_read(addr,o1,n1,n2) \
611                         AO_compare_and_swap_double(addr,o1,n1,n2)
612 #   define AO_HAVE_compare_and_swap_double_dd_acquire_read
613 # endif
614 #endif
615 
616 /* Convenience functions for AO_double compare-and-swap which types and */
617 /* reads easier in code.                                                */
618 #if defined(AO_HAVE_compare_double_and_swap_double) \
619     && !defined(AO_HAVE_double_compare_and_swap)
620   AO_INLINE int
AO_double_compare_and_swap(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)621   AO_double_compare_and_swap(volatile AO_double_t *addr,
622                              AO_double_t old_val, AO_double_t new_val)
623   {
624     return AO_compare_double_and_swap_double(addr,
625                                         old_val.AO_val1, old_val.AO_val2,
626                                         new_val.AO_val1, new_val.AO_val2);
627   }
628 # define AO_HAVE_double_compare_and_swap
629 #endif
630 #if defined(AO_HAVE_compare_double_and_swap_double_release) \
631     && !defined(AO_HAVE_double_compare_and_swap_release)
632   AO_INLINE int
AO_double_compare_and_swap_release(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)633   AO_double_compare_and_swap_release(volatile AO_double_t *addr,
634                                      AO_double_t old_val, AO_double_t new_val)
635   {
636     return AO_compare_double_and_swap_double_release(addr,
637                                           old_val.AO_val1, old_val.AO_val2,
638                                           new_val.AO_val1, new_val.AO_val2);
639   }
640 # define AO_HAVE_double_compare_and_swap_release
641 #endif
642 #if defined(AO_HAVE_compare_double_and_swap_double_acquire) \
643     && !defined(AO_HAVE_double_compare_and_swap_acquire)
644   AO_INLINE int
AO_double_compare_and_swap_acquire(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)645   AO_double_compare_and_swap_acquire(volatile AO_double_t *addr,
646                                      AO_double_t old_val, AO_double_t new_val)
647   {
648     return AO_compare_double_and_swap_double_acquire(addr,
649                                           old_val.AO_val1, old_val.AO_val2,
650                                           new_val.AO_val1, new_val.AO_val2);
651   }
652 # define AO_HAVE_double_compare_and_swap_acquire
653 #endif
654 #if defined(AO_HAVE_compare_double_and_swap_double_read) \
655     && !defined(AO_HAVE_double_compare_and_swap_read)
656   AO_INLINE int
AO_double_compare_and_swap_read(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)657   AO_double_compare_and_swap_read(volatile AO_double_t *addr,
658                                   AO_double_t old_val, AO_double_t new_val)
659   {
660     return AO_compare_double_and_swap_double_read(addr,
661                                           old_val.AO_val1, old_val.AO_val2,
662                                           new_val.AO_val1, new_val.AO_val2);
663   }
664 # define AO_HAVE_double_compare_and_swap_read
665 #endif
666 #if defined(AO_HAVE_compare_double_and_swap_double_write) \
667     && !defined(AO_HAVE_double_compare_and_swap_write)
668   AO_INLINE int
AO_double_compare_and_swap_write(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)669   AO_double_compare_and_swap_write(volatile AO_double_t *addr,
670                                    AO_double_t old_val, AO_double_t new_val)
671   {
672     return AO_compare_double_and_swap_double_write(addr,
673                                           old_val.AO_val1, old_val.AO_val2,
674                                           new_val.AO_val1, new_val.AO_val2);
675   }
676 # define AO_HAVE_double_compare_and_swap_write
677 #endif
678 #if defined(AO_HAVE_compare_double_and_swap_double_release_write) \
679     && !defined(AO_HAVE_double_compare_and_swap_release_write)
680   AO_INLINE int
AO_double_compare_and_swap_release_write(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)681   AO_double_compare_and_swap_release_write(volatile AO_double_t *addr,
682                                 AO_double_t old_val, AO_double_t new_val)
683   {
684     return AO_compare_double_and_swap_double_release_write(addr,
685                                           old_val.AO_val1, old_val.AO_val2,
686                                           new_val.AO_val1, new_val.AO_val2);
687   }
688 # define AO_HAVE_double_compare_and_swap_release_write
689 #endif
690 #if defined(AO_HAVE_compare_double_and_swap_double_acquire_read) \
691     && !defined(AO_HAVE_double_compare_and_swap_acquire_read)
692   AO_INLINE int
AO_double_compare_and_swap_acquire_read(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)693   AO_double_compare_and_swap_acquire_read(volatile AO_double_t *addr,
694                                 AO_double_t old_val, AO_double_t new_val)
695   {
696     return AO_compare_double_and_swap_double_acquire_read(addr,
697                                           old_val.AO_val1, old_val.AO_val2,
698                                           new_val.AO_val1, new_val.AO_val2);
699   }
700 # define AO_HAVE_double_compare_and_swap_acquire_read
701 #endif
702 #if defined(AO_HAVE_compare_double_and_swap_double_full) \
703     && !defined(AO_HAVE_double_compare_and_swap_full)
704   AO_INLINE int
AO_double_compare_and_swap_full(volatile AO_double_t * addr,AO_double_t old_val,AO_double_t new_val)705   AO_double_compare_and_swap_full(volatile AO_double_t *addr,
706                                   AO_double_t old_val, AO_double_t new_val)
707   {
708     return AO_compare_double_and_swap_double_full(addr,
709                                           old_val.AO_val1, old_val.AO_val2,
710                                           new_val.AO_val1, new_val.AO_val2);
711   }
712 # define AO_HAVE_double_compare_and_swap_full
713 #endif
714 
715 #ifndef AO_HAVE_double_compare_and_swap_dd_acquire_read
716   /* Duplicated from generalize-small because double CAS might be       */
717   /* defined after the include.                                         */
718 # ifdef AO_NO_DD_ORDERING
719 #   if defined(AO_HAVE_double_compare_and_swap_acquire_read)
720 #     define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \
721                 AO_double_compare_and_swap_acquire_read(addr, old, new_val)
722 #     define AO_HAVE_double_compare_and_swap_dd_acquire_read
723 #   endif
724 # elif defined(AO_HAVE_double_compare_and_swap)
725 #   define AO_double_compare_and_swap_dd_acquire_read(addr, old, new_val) \
726                 AO_double_compare_and_swap(addr, old, new_val)
727 #   define AO_HAVE_double_compare_and_swap_dd_acquire_read
728 # endif /* !AO_NO_DD_ORDERING */
729 #endif
730