1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2014-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 /*
22 * Description: Native double word atomics using libatomic_ops
23 * Author: Rickard Green
24 */
25
26 #ifndef ETHR_LIBATOMIC_OPS_DW_ATOMIC_H__
27 #define ETHR_LIBATOMIC_OPS_DW_ATOMIC_H__
28
29 #if defined(AO_HAVE_double_t) \
30 && (defined(AO_HAVE_double_load_acquire) \
31 || defined(AO_HAVE_double_load)) \
32 && (defined(AO_HAVE_compare_double_and_swap_double) \
33 || defined(AO_HAVE_compare_double_and_swap_double_full) \
34 || defined(AO_HAVE_compare_double_and_swap_double_acquire) \
35 || defined(AO_HAVE_compare_double_and_swap_double_release) \
36 || defined(AO_HAVE_double_compare_and_swap) \
37 || defined(AO_HAVE_double_compare_and_swap_full) \
38 || defined(AO_HAVE_double_compare_and_swap_acquire) \
39 || defined(AO_HAVE_double_compare_and_swap_release))
40
41 #if ETHR_SIZEOF_PTR == 4
42 # define ETHR_NATIVE_SU_DW_SINT_T ethr_sint64_t
43 #elif ETHR_SIZEOF_PTR == 8 && defined(ETHR_HAVE_INT128_T)
44 # define ETHR_NATIVE_SU_DW_SINT_T ethr_sint128_t
45 #endif
46
47 typedef union {
48 volatile AO_double_t dw_mem;
49 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
50 ETHR_NATIVE_SU_DW_SINT_T su_dw_sint;
51 #endif
52 } ethr_native_dw_atomic_t;
53
54 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
55 # define ETHR_HAVE_NATIVE_SU_DW_ATOMIC
56 #else
57 # define ETHR_HAVE_NATIVE_DW_ATOMIC
58 #endif
59
60 #define ETHR_NATIVE_DW_ATOMIC_IMPL ETHR_NATIVE_IMPL__
61
62 #if defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__)
63
64
65 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
66 # define ETHR_NDWA_FUNC__(Func) ethr_native_su_dw_atomic_ ## Func
67 # define ETHR_NDWA_RET_3_TYPE__ ETHR_NATIVE_SU_DW_SINT_T
68 # define ETHR_NDWA_RET_2_TYPE__ ETHR_NATIVE_SU_DW_SINT_T
69 # define ETHR_NDWA_VAL_ARG_TYPE__ ETHR_NATIVE_SU_DW_SINT_T
70 # define ETHR_NDWA_DECL_ARG__(Arg)
71 # if defined(AO_HAVE_DOUBLE_PTR_STORAGE)
72 # define ETHR_NDWA_VAL2AOVAL__(AOV, V) \
73 ((AOV).AO_whole = (double_ptr_storage) (V))
74 # define ETHR_NDWA_AOVAL2VAL__(AOV, V) \
75 ((V) = (ETHR_NATIVE_SU_DW_SINT_T) (AOV).AO_whole)
76 # define ETHR_NDWA_RETURN_VAL_3__(SUCCESS, AOVAL, VAL) \
77 do { \
78 return (ETHR_NATIVE_SU_DW_SINT_T) (AOVAL).AO_whole; \
79 } while (0)
80 # define ETHR_NDWA_RETURN_VAL_2__(AOVAL, VAL) \
81 do { \
82 return (ETHR_NATIVE_SU_DW_SINT_T) (AOVAL).AO_whole; \
83 } while (0)
84 # define ETHR_NDWA_AOVAL_EQ__(AOV1, AOV2) \
85 ((AOV1).AO_whole == (AOV2).AO_whole)
86 # else
87 typedef union {
88 ethr_sint_t sint[2];
89 ETHR_NATIVE_SU_DW_SINT_T dw_sint;
90 } ethr_dw_splitter_t;
91 # define ETHR_NDWA_VAL2AOVAL__(AOV, V) \
92 do { \
93 ethr_dw_splitter_t tmp__; \
94 tmp__.dw_sint = (V); \
95 (AOV).AO_val1 = (AO_t) tmp__.sint[0]; \
96 (AOV).AO_val2 = (AO_t) tmp__.sint[1]; \
97 } while (0)
98 # define ETHR_NDWA_AOVAL2VAL__(AOV, V) \
99 do { \
100 ethr_dw_splitter_t tmp__; \
101 tmp__.sint[0] = (ethr_sint_t) (AOV).AO_val1; \
102 tmp__.sint[1] = (ethr_sint_t) (AOV).AO_val2; \
103 (V) = tmp__.dw_sint; \
104 } while (0)
105 # define ETHR_NDWA_RETURN_VAL_3__(SUCCESS, AOVAL, VAL) \
106 do { \
107 ethr_dw_splitter_t tmp__; \
108 tmp__.sint[0] = (ethr_sint_t) (AOVAL).AO_val1; \
109 tmp__.sint[1] = (ethr_sint_t) (AOVAL).AO_val2; \
110 return tmp__.dw_sint; \
111 } while (0)
112 # define ETHR_NDWA_AOVAL_EQ__(AOV1, AOV2) \
113 ((AOV1).AO_val1 == (AOV2).AO_val1 \
114 && (AOV1).AO_val2 == (AOV2).AO_val2)
115 # endif
116 #else
117 # define ETHR_NDWA_FUNC__(Func) ethr_native_dw_atomic_ ## Func
118 # define ETHR_NDWA_RET_3_TYPE__ int
119 # define ETHR_NDWA_RET_2_TYPE__ void
120 # define ETHR_NDWA_VAL_ARG_TYPE__ ethr_sint_t *
121 # define ETHR_NDWA_DECL_ARG__(Arg) , ETHR_NDWA_VAL_ARG_TYPE__ Arg
122 # define ETHR_NDWA_VAL2AOVAL__(AOV, V) \
123 do { \
124 (AOV).AO_val1 = (AO_t) (V)[0]; \
125 (AOV).AO_val2 = (AO_t) (V)[1]; \
126 } while (0)
127 # define ETHR_NDWA_AOVAL2VAL__(AOV, V) \
128 do { \
129 ethr_dw_splitter_t tmp__; \
130 (V)[0] = (ethr_sint_t) (AOV).AO_val1; \
131 (V)[1] = (ethr_sint_t) (AOV).AO_val2; \
132 } while (0)
133 # define ETHR_NDWA_RETURN_VAL_3__(SUCCESS, AOVAL, VAL) \
134 do { \
135 (VAL)[0] = (ethr_sint_t) (AOVAL).AO_val1; \
136 (VAL)[1] = (ethr_sint_t) (AOVAL).AO_val2; \
137 return (SUCCESS); \
138 } while (0)
139 # define ETHR_NDWA_RETURN_VAL_2__(AOVAL, VAL) \
140 do { \
141 (VAL)[0] = (ethr_sint_t) (AOVAL).AO_val1; \
142 (VAL)[1] = (ethr_sint_t) (AOVAL).AO_val2; \
143 return; \
144 } while (0)
145 # if defined(AO_HAVE_DOUBLE_PTR_STORAGE)
146 # define ETHR_NDWA_AOVAL_EQ__(AOV1, AOV2) \
147 ((AOV1).AO_whole == (AOV2).AO_whole)
148 # else
149 # define ETHR_NDWA_AOVAL_EQ__(AOV1, AOV2) \
150 ((AOV1).AO_val1 == (AOV2).AO_val1 \
151 && (AOV1).AO_val2 == (AOV2).AO_val2)
152 # endif
153 #endif
154
155 #define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_ADDR
156 static ETHR_INLINE ethr_sint_t *
ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t * var)157 ethr_native_dw_atomic_addr(ethr_native_dw_atomic_t *var)
158 {
159 return (ethr_sint_t *) &var->dw_mem;
160 }
161
162 #ifdef AO_HAVE_double_load
163
164 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
165 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ
166 #else
167 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ
168 #endif
169
170 static ETHR_INLINE ETHR_NDWA_RET_2_TYPE__
ETHR_NDWA_FUNC__(read)171 ETHR_NDWA_FUNC__(read)(ethr_native_dw_atomic_t *var
172 ETHR_NDWA_DECL_ARG__(val))
173 {
174 AO_double_t act = AO_double_load(&var->dw_mem);
175 ETHR_NDWA_RETURN_VAL_2__(act, val);
176 }
177
178 #endif
179
180 #ifdef AO_HAVE_double_load_read
181
182 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
183 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_RB
184 #else
185 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_RB
186 #endif
187
188 static ETHR_INLINE ETHR_NDWA_RET_2_TYPE__
ETHR_NDWA_FUNC__(read_rb)189 ETHR_NDWA_FUNC__(read_rb)(ethr_native_dw_atomic_t *var
190 ETHR_NDWA_DECL_ARG__(val))
191 {
192 AO_double_t act = AO_double_load_read(&var->dw_mem);
193 ETHR_NDWA_RETURN_VAL_2__(act, val);
194 }
195
196 #endif
197
198 #ifdef AO_HAVE_double_load_acquire
199
200 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
201 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_READ_ACQB
202 #else
203 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_READ_ACQB
204 #endif
205
206 static ETHR_INLINE ETHR_NDWA_RET_2_TYPE__
ETHR_NDWA_FUNC__(read_acqb)207 ETHR_NDWA_FUNC__(read_acqb)(ethr_native_dw_atomic_t *var
208 ETHR_NDWA_DECL_ARG__(val))
209 {
210 AO_double_t act = AO_double_load_acquire(&var->dw_mem);
211 ETHR_NDWA_RETURN_VAL_2__(act, val);
212 }
213
214 #endif
215
216 #ifdef AO_HAVE_double_store
217
218 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
219 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET
220 #else
221 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET
222 #endif
223
224 static ETHR_INLINE void
ETHR_NDWA_FUNC__(set)225 ETHR_NDWA_FUNC__(set)(ethr_native_dw_atomic_t *var,
226 ETHR_NDWA_VAL_ARG_TYPE__ val)
227 {
228 AO_double_t new;
229 ETHR_NDWA_VAL2AOVAL__(new, val);
230 AO_double_store(&var->dw_mem, new);
231 }
232
233 #endif
234
235 #ifdef AO_HAVE_double_store_write
236
237 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
238 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_WB
239 #else
240 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_WB
241 #endif
242
243 static ETHR_INLINE void
ETHR_NDWA_FUNC__(set_wb)244 ETHR_NDWA_FUNC__(set_wb)(ethr_native_dw_atomic_t *var,
245 ETHR_NDWA_VAL_ARG_TYPE__ val)
246 {
247 AO_double_t new;
248 ETHR_NDWA_VAL2AOVAL__(new, val);
249 AO_double_store_write(&var->dw_mem, new);
250 }
251
252 #endif
253
254 #ifdef AO_HAVE_double_store_release
255
256 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
257 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_SET_RELB
258 #else
259 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_SET_RELB
260 #endif
261
262 static ETHR_INLINE void
ETHR_NDWA_FUNC__(set_relb)263 ETHR_NDWA_FUNC__(set_relb)(ethr_native_dw_atomic_t *var,
264 ETHR_NDWA_VAL_ARG_TYPE__ val)
265 {
266 AO_double_t new;
267 ETHR_NDWA_VAL2AOVAL__(new, val);
268 AO_double_store_release(&var->dw_mem, new);
269 }
270
271 #endif
272
273 #if defined(AO_HAVE_double_compare_and_swap_full) || defined(AO_HAVE_compare_double_and_swap_double_full)
274
275 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
276 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_MB
277 #else
278 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_MB
279 #endif
280
281 static ETHR_INLINE ETHR_NDWA_RET_3_TYPE__
ETHR_NDWA_FUNC__(cmpxchg_mb)282 ETHR_NDWA_FUNC__(cmpxchg_mb)(ethr_native_dw_atomic_t *var,
283 ETHR_NDWA_VAL_ARG_TYPE__ new,
284 ETHR_NDWA_VAL_ARG_TYPE__ exp)
285 {
286 AO_double_t ao_act, ao_new, ao_exp;
287
288 ETHR_NDWA_VAL2AOVAL__(ao_exp, exp);
289 ETHR_NDWA_VAL2AOVAL__(ao_new, new);
290
291 do {
292 int xchgd;
293 #if defined(AO_HAVE_double_compare_and_swap_full)
294 xchgd = AO_double_compare_and_swap_full(&var->dw_mem, ao_exp, ao_new);
295 #elif defined(AO_HAVE_compare_double_and_swap_double_full)
296 xchgd = AO_compare_double_and_swap_double_full(&var->dw_mem,
297 ao_exp.AO_val1,
298 ao_exp.AO_val2,
299 ao_new.AO_val1,
300 ao_new.AO_val2);
301 #endif
302
303 if (xchgd)
304 ETHR_NDWA_RETURN_VAL_3__(1, ao_exp, exp);
305
306 #ifdef AO_HAVE_double_load_acquire
307 ao_act = AO_double_load_acquire(&var->dw_mem);
308 #else
309 ao_act = AO_double_load(&var->dw_mem);
310 #endif
311
312 } while (ETHR_NDWA_AOVAL_EQ__(ao_exp, ao_act));
313
314 #ifndef AO_HAVE_double_load_acquire
315 AO_nop_full();
316 #endif
317
318 ETHR_NDWA_RETURN_VAL_3__(1, ao_act, exp);
319 }
320
321 #endif
322
323 #if defined(AO_HAVE_double_compare_and_swap) || defined(AO_HAVE_compare_double_and_swap_double)
324
325 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
326 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG
327 #else
328 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG
329 #endif
330
331 static ETHR_INLINE ETHR_NDWA_RET_3_TYPE__
ETHR_NDWA_FUNC__(cmpxchg)332 ETHR_NDWA_FUNC__(cmpxchg)(ethr_native_dw_atomic_t *var,
333 ETHR_NDWA_VAL_ARG_TYPE__ new,
334 ETHR_NDWA_VAL_ARG_TYPE__ exp)
335 {
336 AO_double_t ao_act, ao_new, ao_exp;
337
338 ETHR_NDWA_VAL2AOVAL__(ao_exp, exp);
339 ETHR_NDWA_VAL2AOVAL__(ao_new, new);
340
341 do {
342 int xchgd;
343 #if defined(AO_HAVE_double_compare_and_swap)
344 xchgd = AO_double_compare_and_swap(&var->dw_mem, ao_exp, ao_new);
345 #elif defined(AO_HAVE_compare_double_and_swap_double)
346 xchgd = AO_compare_double_and_swap_double(&var->dw_mem,
347 ao_exp.AO_val1,
348 ao_exp.AO_val2,
349 ao_new.AO_val1,
350 ao_new.AO_val2);
351 #endif
352
353 if (xchgd)
354 ETHR_NDWA_RETURN_VAL_3__(1, ao_exp, exp);
355
356 #ifdef AO_HAVE_double_load
357 ao_act = AO_double_load(&var->dw_mem);
358 #else
359 ao_act = AO_double_load_acquire(&var->dw_mem);
360 #endif
361
362 } while (ETHR_NDWA_AOVAL_EQ__(ao_exp, ao_act));
363
364 ETHR_NDWA_RETURN_VAL_3__(1, ao_act, exp);
365 }
366
367 #endif
368
369 #if defined(AO_HAVE_double_compare_and_swap_read) || defined(AO_HAVE_compare_double_and_swap_double_read)
370
371 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
372 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_RB
373 #else
374 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_RB
375 #endif
376
377 static ETHR_INLINE ETHR_NDWA_RET_3_TYPE__
ETHR_NDWA_FUNC__(cmpxchg_rb)378 ETHR_NDWA_FUNC__(cmpxchg_rb)(ethr_native_dw_atomic_t *var,
379 ETHR_NDWA_VAL_ARG_TYPE__ new,
380 ETHR_NDWA_VAL_ARG_TYPE__ exp)
381 {
382 AO_double_t ao_act, ao_new, ao_exp;
383
384 ETHR_NDWA_VAL2AOVAL__(ao_exp, exp);
385 ETHR_NDWA_VAL2AOVAL__(ao_new, new);
386
387 do {
388 int xchgd;
389 #if defined(AO_HAVE_double_compare_and_swap_read)
390 xchgd = AO_double_compare_and_swap_read(&var->dw_mem, ao_exp, ao_new);
391 #elif defined(AO_HAVE_compare_double_and_swap_double_read)
392 xchgd = AO_compare_double_and_swap_double_read(&var->dw_mem,
393 ao_exp.AO_val1,
394 ao_exp.AO_val2,
395 ao_new.AO_val1,
396 ao_new.AO_val2);
397 #endif
398
399 if (xchgd)
400 ETHR_NDWA_RETURN_VAL_3__(1, ao_exp, exp);
401
402 #if defined(AO_HAVE_double_load_read)
403 ao_act = AO_double_load_read(&var->dw_mem);
404 #elif defined(AO_HAVE_double_load)
405 ao_act = AO_double_load(&var->dw_mem);
406 #else
407 ao_act = AO_double_load_acquire(&var->dw_mem);
408 #endif
409
410 } while (ETHR_NDWA_AOVAL_EQ__(ao_exp, ao_act));
411
412 #ifndef AO_HAVE_double_load_read
413 #ifdef AO_HAVE_nop_read
414 AO_nop_read();
415 #else
416 AO_nop_full();
417 #endif
418 #endif
419
420 ETHR_NDWA_RETURN_VAL_3__(1, ao_act, exp);
421 }
422
423 #endif
424
425 #if defined(AO_HAVE_double_compare_and_swap_acquire) || defined(AO_HAVE_compare_double_and_swap_double_acquire)
426
427 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
428 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_ACQB
429 #else
430 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_ACQB
431 #endif
432
433 static ETHR_INLINE ETHR_NDWA_RET_3_TYPE__
ETHR_NDWA_FUNC__(cmpxchg_acqb)434 ETHR_NDWA_FUNC__(cmpxchg_acqb)(ethr_native_dw_atomic_t *var,
435 ETHR_NDWA_VAL_ARG_TYPE__ new,
436 ETHR_NDWA_VAL_ARG_TYPE__ exp)
437 {
438 AO_double_t ao_act, ao_new, ao_exp;
439
440 ETHR_NDWA_VAL2AOVAL__(ao_exp, exp);
441 ETHR_NDWA_VAL2AOVAL__(ao_new, new);
442
443 do {
444 int xchgd;
445 #if defined(AO_HAVE_double_compare_and_swap_acquire)
446 xchgd = AO_double_compare_and_swap_acquire(&var->dw_mem, ao_exp, ao_new);
447 #elif defined(AO_HAVE_compare_double_and_swap_double_acquire)
448 xchgd = AO_compare_double_and_swap_double_acquire(&var->dw_mem,
449 ao_exp.AO_val1,
450 ao_exp.AO_val2,
451 ao_new.AO_val1,
452 ao_new.AO_val2);
453 #endif
454
455 if (xchgd)
456 ETHR_NDWA_RETURN_VAL_3__(1, ao_exp, exp);
457
458 #ifdef AO_HAVE_double_load_acquire
459 ao_act = AO_double_load_acquire(&var->dw_mem);
460 #else
461 ao_act = AO_double_load(&var->dw_mem);
462 #endif
463
464 } while (ETHR_NDWA_AOVAL_EQ__(ao_exp, ao_act));
465
466 #ifndef AO_HAVE_double_load_acquire
467 AO_nop_full();
468 #endif
469
470 ETHR_NDWA_RETURN_VAL_3__(1, ao_act, exp);
471 }
472
473 #endif
474
475 #if defined(AO_HAVE_double_compare_and_swap_write) || defined(AO_HAVE_compare_double_and_swap_double_write)
476
477 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
478 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_WB
479 #else
480 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_WB
481 #endif
482
483 static ETHR_INLINE ETHR_NDWA_RET_3_TYPE__
ETHR_NDWA_FUNC__(cmpxchg_wb)484 ETHR_NDWA_FUNC__(cmpxchg_wb)(ethr_native_dw_atomic_t *var,
485 ETHR_NDWA_VAL_ARG_TYPE__ new,
486 ETHR_NDWA_VAL_ARG_TYPE__ exp)
487 {
488 AO_double_t ao_act, ao_new, ao_exp;
489
490 ETHR_NDWA_VAL2AOVAL__(ao_exp, exp);
491 ETHR_NDWA_VAL2AOVAL__(ao_new, new);
492
493 do {
494 int xchgd;
495 #if defined(AO_HAVE_double_compare_and_swap_write)
496 xchgd = AO_double_compare_and_swap_write(&var->dw_mem, ao_exp, ao_new);
497 #elif defined(AO_HAVE_compare_double_and_swap_double_write)
498 xchgd = AO_compare_double_and_swap_double_write(&var->dw_mem,
499 ao_exp.AO_val1,
500 ao_exp.AO_val2,
501 ao_new.AO_val1,
502 ao_new.AO_val2);
503 #endif
504
505 if (xchgd)
506 ETHR_NDWA_RETURN_VAL_3__(1, ao_exp, exp);
507
508 #ifdef AO_HAVE_double_load
509 ao_act = AO_double_load(&var->dw_mem);
510 #else
511 ao_act = AO_double_load_acquire(&var->dw_mem);
512 #endif
513
514 } while (ETHR_NDWA_AOVAL_EQ__(ao_exp, ao_act));
515
516 ETHR_NDWA_RETURN_VAL_3__(1, ao_act, exp);
517 }
518
519 #endif
520
521 #if defined(AO_HAVE_double_compare_and_swap_release) || defined(AO_HAVE_compare_double_and_swap_double_release)
522
523 #if defined(ETHR_NATIVE_SU_DW_SINT_T)
524 # define ETHR_HAVE_ETHR_NATIVE_SU_DW_ATOMIC_CMPXCHG_RELB
525 #else
526 # define ETHR_HAVE_ETHR_NATIVE_DW_ATOMIC_CMPXCHG_RELB
527 #endif
528
529 static ETHR_INLINE ETHR_NDWA_RET_3_TYPE__
ETHR_NDWA_FUNC__(cmpxchg_relb)530 ETHR_NDWA_FUNC__(cmpxchg_relb)(ethr_native_dw_atomic_t *var,
531 ETHR_NDWA_VAL_ARG_TYPE__ new,
532 ETHR_NDWA_VAL_ARG_TYPE__ exp)
533 {
534 AO_double_t ao_act, ao_new, ao_exp;
535
536 ETHR_NDWA_VAL2AOVAL__(ao_exp, exp);
537 ETHR_NDWA_VAL2AOVAL__(ao_new, new);
538
539 do {
540 int xchgd;
541 #if defined(AO_HAVE_double_compare_and_swap_release)
542 xchgd = AO_double_compare_and_swap_release(&var->dw_mem, ao_exp, ao_new);
543 #elif defined(AO_HAVE_compare_double_and_swap_double_release)
544 xchgd = AO_compare_double_and_swap_double_release(&var->dw_mem,
545 ao_exp.AO_val1,
546 ao_exp.AO_val2,
547 ao_new.AO_val1,
548 ao_new.AO_val2);
549 #endif
550
551 if (xchgd)
552 ETHR_NDWA_RETURN_VAL_3__(1, ao_exp, exp);
553
554 ao_act = AO_double_load(&var->dw_mem);
555
556 } while (ETHR_NDWA_AOVAL_EQ__(ao_exp, ao_act));
557
558 ETHR_NDWA_RETURN_VAL_3__(1, ao_act, exp);
559 }
560
561 #endif
562
563 #endif /* defined(ETHR_TRY_INLINE_FUNCS) || defined(ETHR_ATOMIC_IMPL__) */
564
565 #endif /* Have AO double functionality ... */
566
567 #endif /* ETHR_LIBATOMIC_OPS_DW_ATOMIC_H__ */
568
569