10b57cec5SDimitry Andric /*
20b57cec5SDimitry Andric * kmp_atomic.cpp -- ATOMIC implementation routines
30b57cec5SDimitry Andric */
40b57cec5SDimitry Andric
50b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
80b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
90b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "kmp_atomic.h"
140b57cec5SDimitry Andric #include "kmp.h" // TRUE, asm routines prototypes
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric typedef unsigned char uchar;
170b57cec5SDimitry Andric typedef unsigned short ushort;
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric /*!
200b57cec5SDimitry Andric @defgroup ATOMIC_OPS Atomic Operations
210b57cec5SDimitry Andric These functions are used for implementing the many different varieties of atomic
220b57cec5SDimitry Andric operations.
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric The compiler is at liberty to inline atomic operations that are naturally
250b57cec5SDimitry Andric supported by the target architecture. For instance on IA-32 architecture an
260b57cec5SDimitry Andric atomic like this can be inlined
270b57cec5SDimitry Andric @code
280b57cec5SDimitry Andric static int s = 0;
290b57cec5SDimitry Andric #pragma omp atomic
300b57cec5SDimitry Andric s++;
310b57cec5SDimitry Andric @endcode
320b57cec5SDimitry Andric using the single instruction: `lock; incl s`
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric However the runtime does provide entrypoints for these operations to support
350b57cec5SDimitry Andric compilers that choose not to inline them. (For instance,
360b57cec5SDimitry Andric `__kmpc_atomic_fixed4_add` could be used to perform the increment above.)
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric The names of the functions are encoded by using the data type name and the
390b57cec5SDimitry Andric operation name, as in these tables.
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric Data Type | Data type encoding
420b57cec5SDimitry Andric -----------|---------------
430b57cec5SDimitry Andric int8_t | `fixed1`
440b57cec5SDimitry Andric uint8_t | `fixed1u`
450b57cec5SDimitry Andric int16_t | `fixed2`
460b57cec5SDimitry Andric uint16_t | `fixed2u`
470b57cec5SDimitry Andric int32_t | `fixed4`
480b57cec5SDimitry Andric uint32_t | `fixed4u`
490b57cec5SDimitry Andric int32_t | `fixed8`
500b57cec5SDimitry Andric uint32_t | `fixed8u`
510b57cec5SDimitry Andric float | `float4`
520b57cec5SDimitry Andric double | `float8`
530b57cec5SDimitry Andric float 10 (8087 eighty bit float) | `float10`
540b57cec5SDimitry Andric complex<float> | `cmplx4`
550b57cec5SDimitry Andric complex<double> | `cmplx8`
560b57cec5SDimitry Andric complex<float10> | `cmplx10`
570b57cec5SDimitry Andric <br>
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric Operation | Operation encoding
600b57cec5SDimitry Andric ----------|-------------------
610b57cec5SDimitry Andric + | add
620b57cec5SDimitry Andric - | sub
630b57cec5SDimitry Andric \* | mul
640b57cec5SDimitry Andric / | div
650b57cec5SDimitry Andric & | andb
660b57cec5SDimitry Andric << | shl
670b57cec5SDimitry Andric \>\> | shr
680b57cec5SDimitry Andric \| | orb
690b57cec5SDimitry Andric ^ | xor
700b57cec5SDimitry Andric && | andl
710b57cec5SDimitry Andric \|\| | orl
720b57cec5SDimitry Andric maximum | max
730b57cec5SDimitry Andric minimum | min
740b57cec5SDimitry Andric .eqv. | eqv
750b57cec5SDimitry Andric .neqv. | neqv
760b57cec5SDimitry Andric
770b57cec5SDimitry Andric <br>
780b57cec5SDimitry Andric For non-commutative operations, `_rev` can also be added for the reversed
790b57cec5SDimitry Andric operation. For the functions that capture the result, the suffix `_cpt` is
800b57cec5SDimitry Andric added.
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric Update Functions
830b57cec5SDimitry Andric ================
840b57cec5SDimitry Andric The general form of an atomic function that just performs an update (without a
850b57cec5SDimitry Andric `capture`)
860b57cec5SDimitry Andric @code
870b57cec5SDimitry Andric void __kmpc_atomic_<datatype>_<operation>( ident_t *id_ref, int gtid, TYPE *
880b57cec5SDimitry Andric lhs, TYPE rhs );
890b57cec5SDimitry Andric @endcode
900b57cec5SDimitry Andric @param ident_t a pointer to source location
910b57cec5SDimitry Andric @param gtid the global thread id
920b57cec5SDimitry Andric @param lhs a pointer to the left operand
930b57cec5SDimitry Andric @param rhs the right operand
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric `capture` functions
960b57cec5SDimitry Andric ===================
970b57cec5SDimitry Andric The capture functions perform an atomic update and return a result, which is
980b57cec5SDimitry Andric either the value before the capture, or that after. They take an additional
990b57cec5SDimitry Andric argument to determine which result is returned.
1000b57cec5SDimitry Andric Their general form is therefore
1010b57cec5SDimitry Andric @code
1020b57cec5SDimitry Andric TYPE __kmpc_atomic_<datatype>_<operation>_cpt( ident_t *id_ref, int gtid, TYPE *
1030b57cec5SDimitry Andric lhs, TYPE rhs, int flag );
1040b57cec5SDimitry Andric @endcode
1050b57cec5SDimitry Andric @param ident_t a pointer to source location
1060b57cec5SDimitry Andric @param gtid the global thread id
1070b57cec5SDimitry Andric @param lhs a pointer to the left operand
1080b57cec5SDimitry Andric @param rhs the right operand
1090b57cec5SDimitry Andric @param flag one if the result is to be captured *after* the operation, zero if
1100b57cec5SDimitry Andric captured *before*.
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric The one set of exceptions to this is the `complex<float>` type where the value
1130b57cec5SDimitry Andric is not returned, rather an extra argument pointer is passed.
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric They look like
1160b57cec5SDimitry Andric @code
1170b57cec5SDimitry Andric void __kmpc_atomic_cmplx4_<op>_cpt( ident_t *id_ref, int gtid, kmp_cmplx32 *
1180b57cec5SDimitry Andric lhs, kmp_cmplx32 rhs, kmp_cmplx32 * out, int flag );
1190b57cec5SDimitry Andric @endcode
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric Read and Write Operations
1220b57cec5SDimitry Andric =========================
1230b57cec5SDimitry Andric The OpenMP<sup>*</sup> standard now supports atomic operations that simply
1240b57cec5SDimitry Andric ensure that the value is read or written atomically, with no modification
1250b57cec5SDimitry Andric performed. In many cases on IA-32 architecture these operations can be inlined
1260b57cec5SDimitry Andric since the architecture guarantees that no tearing occurs on aligned objects
1270b57cec5SDimitry Andric accessed with a single memory operation of up to 64 bits in size.
1280b57cec5SDimitry Andric
1290b57cec5SDimitry Andric The general form of the read operations is
1300b57cec5SDimitry Andric @code
1310b57cec5SDimitry Andric TYPE __kmpc_atomic_<type>_rd ( ident_t *id_ref, int gtid, TYPE * loc );
1320b57cec5SDimitry Andric @endcode
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric For the write operations the form is
1350b57cec5SDimitry Andric @code
1360b57cec5SDimitry Andric void __kmpc_atomic_<type>_wr ( ident_t *id_ref, int gtid, TYPE * lhs, TYPE rhs
1370b57cec5SDimitry Andric );
1380b57cec5SDimitry Andric @endcode
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric Full list of functions
1410b57cec5SDimitry Andric ======================
1420b57cec5SDimitry Andric This leads to the generation of 376 atomic functions, as follows.
1430b57cec5SDimitry Andric
144480093f4SDimitry Andric Functions for integers
1450b57cec5SDimitry Andric ---------------------
1460b57cec5SDimitry Andric There are versions here for integers of size 1,2,4 and 8 bytes both signed and
1470b57cec5SDimitry Andric unsigned (where that matters).
1480b57cec5SDimitry Andric @code
1490b57cec5SDimitry Andric __kmpc_atomic_fixed1_add
1500b57cec5SDimitry Andric __kmpc_atomic_fixed1_add_cpt
1510b57cec5SDimitry Andric __kmpc_atomic_fixed1_add_fp
1520b57cec5SDimitry Andric __kmpc_atomic_fixed1_andb
1530b57cec5SDimitry Andric __kmpc_atomic_fixed1_andb_cpt
1540b57cec5SDimitry Andric __kmpc_atomic_fixed1_andl
1550b57cec5SDimitry Andric __kmpc_atomic_fixed1_andl_cpt
1560b57cec5SDimitry Andric __kmpc_atomic_fixed1_div
1570b57cec5SDimitry Andric __kmpc_atomic_fixed1_div_cpt
1580b57cec5SDimitry Andric __kmpc_atomic_fixed1_div_cpt_rev
1590b57cec5SDimitry Andric __kmpc_atomic_fixed1_div_float8
1600b57cec5SDimitry Andric __kmpc_atomic_fixed1_div_fp
1610b57cec5SDimitry Andric __kmpc_atomic_fixed1_div_rev
1620b57cec5SDimitry Andric __kmpc_atomic_fixed1_eqv
1630b57cec5SDimitry Andric __kmpc_atomic_fixed1_eqv_cpt
1640b57cec5SDimitry Andric __kmpc_atomic_fixed1_max
1650b57cec5SDimitry Andric __kmpc_atomic_fixed1_max_cpt
1660b57cec5SDimitry Andric __kmpc_atomic_fixed1_min
1670b57cec5SDimitry Andric __kmpc_atomic_fixed1_min_cpt
1680b57cec5SDimitry Andric __kmpc_atomic_fixed1_mul
1690b57cec5SDimitry Andric __kmpc_atomic_fixed1_mul_cpt
1700b57cec5SDimitry Andric __kmpc_atomic_fixed1_mul_float8
1710b57cec5SDimitry Andric __kmpc_atomic_fixed1_mul_fp
1720b57cec5SDimitry Andric __kmpc_atomic_fixed1_neqv
1730b57cec5SDimitry Andric __kmpc_atomic_fixed1_neqv_cpt
1740b57cec5SDimitry Andric __kmpc_atomic_fixed1_orb
1750b57cec5SDimitry Andric __kmpc_atomic_fixed1_orb_cpt
1760b57cec5SDimitry Andric __kmpc_atomic_fixed1_orl
1770b57cec5SDimitry Andric __kmpc_atomic_fixed1_orl_cpt
1780b57cec5SDimitry Andric __kmpc_atomic_fixed1_rd
1790b57cec5SDimitry Andric __kmpc_atomic_fixed1_shl
1800b57cec5SDimitry Andric __kmpc_atomic_fixed1_shl_cpt
1810b57cec5SDimitry Andric __kmpc_atomic_fixed1_shl_cpt_rev
1820b57cec5SDimitry Andric __kmpc_atomic_fixed1_shl_rev
1830b57cec5SDimitry Andric __kmpc_atomic_fixed1_shr
1840b57cec5SDimitry Andric __kmpc_atomic_fixed1_shr_cpt
1850b57cec5SDimitry Andric __kmpc_atomic_fixed1_shr_cpt_rev
1860b57cec5SDimitry Andric __kmpc_atomic_fixed1_shr_rev
1870b57cec5SDimitry Andric __kmpc_atomic_fixed1_sub
1880b57cec5SDimitry Andric __kmpc_atomic_fixed1_sub_cpt
1890b57cec5SDimitry Andric __kmpc_atomic_fixed1_sub_cpt_rev
1900b57cec5SDimitry Andric __kmpc_atomic_fixed1_sub_fp
1910b57cec5SDimitry Andric __kmpc_atomic_fixed1_sub_rev
1920b57cec5SDimitry Andric __kmpc_atomic_fixed1_swp
1930b57cec5SDimitry Andric __kmpc_atomic_fixed1_wr
1940b57cec5SDimitry Andric __kmpc_atomic_fixed1_xor
1950b57cec5SDimitry Andric __kmpc_atomic_fixed1_xor_cpt
1960b57cec5SDimitry Andric __kmpc_atomic_fixed1u_add_fp
1970b57cec5SDimitry Andric __kmpc_atomic_fixed1u_sub_fp
1980b57cec5SDimitry Andric __kmpc_atomic_fixed1u_mul_fp
1990b57cec5SDimitry Andric __kmpc_atomic_fixed1u_div
2000b57cec5SDimitry Andric __kmpc_atomic_fixed1u_div_cpt
2010b57cec5SDimitry Andric __kmpc_atomic_fixed1u_div_cpt_rev
2020b57cec5SDimitry Andric __kmpc_atomic_fixed1u_div_fp
2030b57cec5SDimitry Andric __kmpc_atomic_fixed1u_div_rev
2040b57cec5SDimitry Andric __kmpc_atomic_fixed1u_shr
2050b57cec5SDimitry Andric __kmpc_atomic_fixed1u_shr_cpt
2060b57cec5SDimitry Andric __kmpc_atomic_fixed1u_shr_cpt_rev
2070b57cec5SDimitry Andric __kmpc_atomic_fixed1u_shr_rev
2080b57cec5SDimitry Andric __kmpc_atomic_fixed2_add
2090b57cec5SDimitry Andric __kmpc_atomic_fixed2_add_cpt
2100b57cec5SDimitry Andric __kmpc_atomic_fixed2_add_fp
2110b57cec5SDimitry Andric __kmpc_atomic_fixed2_andb
2120b57cec5SDimitry Andric __kmpc_atomic_fixed2_andb_cpt
2130b57cec5SDimitry Andric __kmpc_atomic_fixed2_andl
2140b57cec5SDimitry Andric __kmpc_atomic_fixed2_andl_cpt
2150b57cec5SDimitry Andric __kmpc_atomic_fixed2_div
2160b57cec5SDimitry Andric __kmpc_atomic_fixed2_div_cpt
2170b57cec5SDimitry Andric __kmpc_atomic_fixed2_div_cpt_rev
2180b57cec5SDimitry Andric __kmpc_atomic_fixed2_div_float8
2190b57cec5SDimitry Andric __kmpc_atomic_fixed2_div_fp
2200b57cec5SDimitry Andric __kmpc_atomic_fixed2_div_rev
2210b57cec5SDimitry Andric __kmpc_atomic_fixed2_eqv
2220b57cec5SDimitry Andric __kmpc_atomic_fixed2_eqv_cpt
2230b57cec5SDimitry Andric __kmpc_atomic_fixed2_max
2240b57cec5SDimitry Andric __kmpc_atomic_fixed2_max_cpt
2250b57cec5SDimitry Andric __kmpc_atomic_fixed2_min
2260b57cec5SDimitry Andric __kmpc_atomic_fixed2_min_cpt
2270b57cec5SDimitry Andric __kmpc_atomic_fixed2_mul
2280b57cec5SDimitry Andric __kmpc_atomic_fixed2_mul_cpt
2290b57cec5SDimitry Andric __kmpc_atomic_fixed2_mul_float8
2300b57cec5SDimitry Andric __kmpc_atomic_fixed2_mul_fp
2310b57cec5SDimitry Andric __kmpc_atomic_fixed2_neqv
2320b57cec5SDimitry Andric __kmpc_atomic_fixed2_neqv_cpt
2330b57cec5SDimitry Andric __kmpc_atomic_fixed2_orb
2340b57cec5SDimitry Andric __kmpc_atomic_fixed2_orb_cpt
2350b57cec5SDimitry Andric __kmpc_atomic_fixed2_orl
2360b57cec5SDimitry Andric __kmpc_atomic_fixed2_orl_cpt
2370b57cec5SDimitry Andric __kmpc_atomic_fixed2_rd
2380b57cec5SDimitry Andric __kmpc_atomic_fixed2_shl
2390b57cec5SDimitry Andric __kmpc_atomic_fixed2_shl_cpt
2400b57cec5SDimitry Andric __kmpc_atomic_fixed2_shl_cpt_rev
2410b57cec5SDimitry Andric __kmpc_atomic_fixed2_shl_rev
2420b57cec5SDimitry Andric __kmpc_atomic_fixed2_shr
2430b57cec5SDimitry Andric __kmpc_atomic_fixed2_shr_cpt
2440b57cec5SDimitry Andric __kmpc_atomic_fixed2_shr_cpt_rev
2450b57cec5SDimitry Andric __kmpc_atomic_fixed2_shr_rev
2460b57cec5SDimitry Andric __kmpc_atomic_fixed2_sub
2470b57cec5SDimitry Andric __kmpc_atomic_fixed2_sub_cpt
2480b57cec5SDimitry Andric __kmpc_atomic_fixed2_sub_cpt_rev
2490b57cec5SDimitry Andric __kmpc_atomic_fixed2_sub_fp
2500b57cec5SDimitry Andric __kmpc_atomic_fixed2_sub_rev
2510b57cec5SDimitry Andric __kmpc_atomic_fixed2_swp
2520b57cec5SDimitry Andric __kmpc_atomic_fixed2_wr
2530b57cec5SDimitry Andric __kmpc_atomic_fixed2_xor
2540b57cec5SDimitry Andric __kmpc_atomic_fixed2_xor_cpt
2550b57cec5SDimitry Andric __kmpc_atomic_fixed2u_add_fp
2560b57cec5SDimitry Andric __kmpc_atomic_fixed2u_sub_fp
2570b57cec5SDimitry Andric __kmpc_atomic_fixed2u_mul_fp
2580b57cec5SDimitry Andric __kmpc_atomic_fixed2u_div
2590b57cec5SDimitry Andric __kmpc_atomic_fixed2u_div_cpt
2600b57cec5SDimitry Andric __kmpc_atomic_fixed2u_div_cpt_rev
2610b57cec5SDimitry Andric __kmpc_atomic_fixed2u_div_fp
2620b57cec5SDimitry Andric __kmpc_atomic_fixed2u_div_rev
2630b57cec5SDimitry Andric __kmpc_atomic_fixed2u_shr
2640b57cec5SDimitry Andric __kmpc_atomic_fixed2u_shr_cpt
2650b57cec5SDimitry Andric __kmpc_atomic_fixed2u_shr_cpt_rev
2660b57cec5SDimitry Andric __kmpc_atomic_fixed2u_shr_rev
2670b57cec5SDimitry Andric __kmpc_atomic_fixed4_add
2680b57cec5SDimitry Andric __kmpc_atomic_fixed4_add_cpt
2690b57cec5SDimitry Andric __kmpc_atomic_fixed4_add_fp
2700b57cec5SDimitry Andric __kmpc_atomic_fixed4_andb
2710b57cec5SDimitry Andric __kmpc_atomic_fixed4_andb_cpt
2720b57cec5SDimitry Andric __kmpc_atomic_fixed4_andl
2730b57cec5SDimitry Andric __kmpc_atomic_fixed4_andl_cpt
2740b57cec5SDimitry Andric __kmpc_atomic_fixed4_div
2750b57cec5SDimitry Andric __kmpc_atomic_fixed4_div_cpt
2760b57cec5SDimitry Andric __kmpc_atomic_fixed4_div_cpt_rev
2770b57cec5SDimitry Andric __kmpc_atomic_fixed4_div_float8
2780b57cec5SDimitry Andric __kmpc_atomic_fixed4_div_fp
2790b57cec5SDimitry Andric __kmpc_atomic_fixed4_div_rev
2800b57cec5SDimitry Andric __kmpc_atomic_fixed4_eqv
2810b57cec5SDimitry Andric __kmpc_atomic_fixed4_eqv_cpt
2820b57cec5SDimitry Andric __kmpc_atomic_fixed4_max
2830b57cec5SDimitry Andric __kmpc_atomic_fixed4_max_cpt
2840b57cec5SDimitry Andric __kmpc_atomic_fixed4_min
2850b57cec5SDimitry Andric __kmpc_atomic_fixed4_min_cpt
2860b57cec5SDimitry Andric __kmpc_atomic_fixed4_mul
2870b57cec5SDimitry Andric __kmpc_atomic_fixed4_mul_cpt
2880b57cec5SDimitry Andric __kmpc_atomic_fixed4_mul_float8
2890b57cec5SDimitry Andric __kmpc_atomic_fixed4_mul_fp
2900b57cec5SDimitry Andric __kmpc_atomic_fixed4_neqv
2910b57cec5SDimitry Andric __kmpc_atomic_fixed4_neqv_cpt
2920b57cec5SDimitry Andric __kmpc_atomic_fixed4_orb
2930b57cec5SDimitry Andric __kmpc_atomic_fixed4_orb_cpt
2940b57cec5SDimitry Andric __kmpc_atomic_fixed4_orl
2950b57cec5SDimitry Andric __kmpc_atomic_fixed4_orl_cpt
2960b57cec5SDimitry Andric __kmpc_atomic_fixed4_rd
2970b57cec5SDimitry Andric __kmpc_atomic_fixed4_shl
2980b57cec5SDimitry Andric __kmpc_atomic_fixed4_shl_cpt
2990b57cec5SDimitry Andric __kmpc_atomic_fixed4_shl_cpt_rev
3000b57cec5SDimitry Andric __kmpc_atomic_fixed4_shl_rev
3010b57cec5SDimitry Andric __kmpc_atomic_fixed4_shr
3020b57cec5SDimitry Andric __kmpc_atomic_fixed4_shr_cpt
3030b57cec5SDimitry Andric __kmpc_atomic_fixed4_shr_cpt_rev
3040b57cec5SDimitry Andric __kmpc_atomic_fixed4_shr_rev
3050b57cec5SDimitry Andric __kmpc_atomic_fixed4_sub
3060b57cec5SDimitry Andric __kmpc_atomic_fixed4_sub_cpt
3070b57cec5SDimitry Andric __kmpc_atomic_fixed4_sub_cpt_rev
3080b57cec5SDimitry Andric __kmpc_atomic_fixed4_sub_fp
3090b57cec5SDimitry Andric __kmpc_atomic_fixed4_sub_rev
3100b57cec5SDimitry Andric __kmpc_atomic_fixed4_swp
3110b57cec5SDimitry Andric __kmpc_atomic_fixed4_wr
3120b57cec5SDimitry Andric __kmpc_atomic_fixed4_xor
3130b57cec5SDimitry Andric __kmpc_atomic_fixed4_xor_cpt
3140b57cec5SDimitry Andric __kmpc_atomic_fixed4u_add_fp
3150b57cec5SDimitry Andric __kmpc_atomic_fixed4u_sub_fp
3160b57cec5SDimitry Andric __kmpc_atomic_fixed4u_mul_fp
3170b57cec5SDimitry Andric __kmpc_atomic_fixed4u_div
3180b57cec5SDimitry Andric __kmpc_atomic_fixed4u_div_cpt
3190b57cec5SDimitry Andric __kmpc_atomic_fixed4u_div_cpt_rev
3200b57cec5SDimitry Andric __kmpc_atomic_fixed4u_div_fp
3210b57cec5SDimitry Andric __kmpc_atomic_fixed4u_div_rev
3220b57cec5SDimitry Andric __kmpc_atomic_fixed4u_shr
3230b57cec5SDimitry Andric __kmpc_atomic_fixed4u_shr_cpt
3240b57cec5SDimitry Andric __kmpc_atomic_fixed4u_shr_cpt_rev
3250b57cec5SDimitry Andric __kmpc_atomic_fixed4u_shr_rev
3260b57cec5SDimitry Andric __kmpc_atomic_fixed8_add
3270b57cec5SDimitry Andric __kmpc_atomic_fixed8_add_cpt
3280b57cec5SDimitry Andric __kmpc_atomic_fixed8_add_fp
3290b57cec5SDimitry Andric __kmpc_atomic_fixed8_andb
3300b57cec5SDimitry Andric __kmpc_atomic_fixed8_andb_cpt
3310b57cec5SDimitry Andric __kmpc_atomic_fixed8_andl
3320b57cec5SDimitry Andric __kmpc_atomic_fixed8_andl_cpt
3330b57cec5SDimitry Andric __kmpc_atomic_fixed8_div
3340b57cec5SDimitry Andric __kmpc_atomic_fixed8_div_cpt
3350b57cec5SDimitry Andric __kmpc_atomic_fixed8_div_cpt_rev
3360b57cec5SDimitry Andric __kmpc_atomic_fixed8_div_float8
3370b57cec5SDimitry Andric __kmpc_atomic_fixed8_div_fp
3380b57cec5SDimitry Andric __kmpc_atomic_fixed8_div_rev
3390b57cec5SDimitry Andric __kmpc_atomic_fixed8_eqv
3400b57cec5SDimitry Andric __kmpc_atomic_fixed8_eqv_cpt
3410b57cec5SDimitry Andric __kmpc_atomic_fixed8_max
3420b57cec5SDimitry Andric __kmpc_atomic_fixed8_max_cpt
3430b57cec5SDimitry Andric __kmpc_atomic_fixed8_min
3440b57cec5SDimitry Andric __kmpc_atomic_fixed8_min_cpt
3450b57cec5SDimitry Andric __kmpc_atomic_fixed8_mul
3460b57cec5SDimitry Andric __kmpc_atomic_fixed8_mul_cpt
3470b57cec5SDimitry Andric __kmpc_atomic_fixed8_mul_float8
3480b57cec5SDimitry Andric __kmpc_atomic_fixed8_mul_fp
3490b57cec5SDimitry Andric __kmpc_atomic_fixed8_neqv
3500b57cec5SDimitry Andric __kmpc_atomic_fixed8_neqv_cpt
3510b57cec5SDimitry Andric __kmpc_atomic_fixed8_orb
3520b57cec5SDimitry Andric __kmpc_atomic_fixed8_orb_cpt
3530b57cec5SDimitry Andric __kmpc_atomic_fixed8_orl
3540b57cec5SDimitry Andric __kmpc_atomic_fixed8_orl_cpt
3550b57cec5SDimitry Andric __kmpc_atomic_fixed8_rd
3560b57cec5SDimitry Andric __kmpc_atomic_fixed8_shl
3570b57cec5SDimitry Andric __kmpc_atomic_fixed8_shl_cpt
3580b57cec5SDimitry Andric __kmpc_atomic_fixed8_shl_cpt_rev
3590b57cec5SDimitry Andric __kmpc_atomic_fixed8_shl_rev
3600b57cec5SDimitry Andric __kmpc_atomic_fixed8_shr
3610b57cec5SDimitry Andric __kmpc_atomic_fixed8_shr_cpt
3620b57cec5SDimitry Andric __kmpc_atomic_fixed8_shr_cpt_rev
3630b57cec5SDimitry Andric __kmpc_atomic_fixed8_shr_rev
3640b57cec5SDimitry Andric __kmpc_atomic_fixed8_sub
3650b57cec5SDimitry Andric __kmpc_atomic_fixed8_sub_cpt
3660b57cec5SDimitry Andric __kmpc_atomic_fixed8_sub_cpt_rev
3670b57cec5SDimitry Andric __kmpc_atomic_fixed8_sub_fp
3680b57cec5SDimitry Andric __kmpc_atomic_fixed8_sub_rev
3690b57cec5SDimitry Andric __kmpc_atomic_fixed8_swp
3700b57cec5SDimitry Andric __kmpc_atomic_fixed8_wr
3710b57cec5SDimitry Andric __kmpc_atomic_fixed8_xor
3720b57cec5SDimitry Andric __kmpc_atomic_fixed8_xor_cpt
3730b57cec5SDimitry Andric __kmpc_atomic_fixed8u_add_fp
3740b57cec5SDimitry Andric __kmpc_atomic_fixed8u_sub_fp
3750b57cec5SDimitry Andric __kmpc_atomic_fixed8u_mul_fp
3760b57cec5SDimitry Andric __kmpc_atomic_fixed8u_div
3770b57cec5SDimitry Andric __kmpc_atomic_fixed8u_div_cpt
3780b57cec5SDimitry Andric __kmpc_atomic_fixed8u_div_cpt_rev
3790b57cec5SDimitry Andric __kmpc_atomic_fixed8u_div_fp
3800b57cec5SDimitry Andric __kmpc_atomic_fixed8u_div_rev
3810b57cec5SDimitry Andric __kmpc_atomic_fixed8u_shr
3820b57cec5SDimitry Andric __kmpc_atomic_fixed8u_shr_cpt
3830b57cec5SDimitry Andric __kmpc_atomic_fixed8u_shr_cpt_rev
3840b57cec5SDimitry Andric __kmpc_atomic_fixed8u_shr_rev
3850b57cec5SDimitry Andric @endcode
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric Functions for floating point
3880b57cec5SDimitry Andric ----------------------------
3890b57cec5SDimitry Andric There are versions here for floating point numbers of size 4, 8, 10 and 16
3900b57cec5SDimitry Andric bytes. (Ten byte floats are used by X87, but are now rare).
3910b57cec5SDimitry Andric @code
3920b57cec5SDimitry Andric __kmpc_atomic_float4_add
3930b57cec5SDimitry Andric __kmpc_atomic_float4_add_cpt
3940b57cec5SDimitry Andric __kmpc_atomic_float4_add_float8
3950b57cec5SDimitry Andric __kmpc_atomic_float4_add_fp
3960b57cec5SDimitry Andric __kmpc_atomic_float4_div
3970b57cec5SDimitry Andric __kmpc_atomic_float4_div_cpt
3980b57cec5SDimitry Andric __kmpc_atomic_float4_div_cpt_rev
3990b57cec5SDimitry Andric __kmpc_atomic_float4_div_float8
4000b57cec5SDimitry Andric __kmpc_atomic_float4_div_fp
4010b57cec5SDimitry Andric __kmpc_atomic_float4_div_rev
4020b57cec5SDimitry Andric __kmpc_atomic_float4_max
4030b57cec5SDimitry Andric __kmpc_atomic_float4_max_cpt
4040b57cec5SDimitry Andric __kmpc_atomic_float4_min
4050b57cec5SDimitry Andric __kmpc_atomic_float4_min_cpt
4060b57cec5SDimitry Andric __kmpc_atomic_float4_mul
4070b57cec5SDimitry Andric __kmpc_atomic_float4_mul_cpt
4080b57cec5SDimitry Andric __kmpc_atomic_float4_mul_float8
4090b57cec5SDimitry Andric __kmpc_atomic_float4_mul_fp
4100b57cec5SDimitry Andric __kmpc_atomic_float4_rd
4110b57cec5SDimitry Andric __kmpc_atomic_float4_sub
4120b57cec5SDimitry Andric __kmpc_atomic_float4_sub_cpt
4130b57cec5SDimitry Andric __kmpc_atomic_float4_sub_cpt_rev
4140b57cec5SDimitry Andric __kmpc_atomic_float4_sub_float8
4150b57cec5SDimitry Andric __kmpc_atomic_float4_sub_fp
4160b57cec5SDimitry Andric __kmpc_atomic_float4_sub_rev
4170b57cec5SDimitry Andric __kmpc_atomic_float4_swp
4180b57cec5SDimitry Andric __kmpc_atomic_float4_wr
4190b57cec5SDimitry Andric __kmpc_atomic_float8_add
4200b57cec5SDimitry Andric __kmpc_atomic_float8_add_cpt
4210b57cec5SDimitry Andric __kmpc_atomic_float8_add_fp
4220b57cec5SDimitry Andric __kmpc_atomic_float8_div
4230b57cec5SDimitry Andric __kmpc_atomic_float8_div_cpt
4240b57cec5SDimitry Andric __kmpc_atomic_float8_div_cpt_rev
4250b57cec5SDimitry Andric __kmpc_atomic_float8_div_fp
4260b57cec5SDimitry Andric __kmpc_atomic_float8_div_rev
4270b57cec5SDimitry Andric __kmpc_atomic_float8_max
4280b57cec5SDimitry Andric __kmpc_atomic_float8_max_cpt
4290b57cec5SDimitry Andric __kmpc_atomic_float8_min
4300b57cec5SDimitry Andric __kmpc_atomic_float8_min_cpt
4310b57cec5SDimitry Andric __kmpc_atomic_float8_mul
4320b57cec5SDimitry Andric __kmpc_atomic_float8_mul_cpt
4330b57cec5SDimitry Andric __kmpc_atomic_float8_mul_fp
4340b57cec5SDimitry Andric __kmpc_atomic_float8_rd
4350b57cec5SDimitry Andric __kmpc_atomic_float8_sub
4360b57cec5SDimitry Andric __kmpc_atomic_float8_sub_cpt
4370b57cec5SDimitry Andric __kmpc_atomic_float8_sub_cpt_rev
4380b57cec5SDimitry Andric __kmpc_atomic_float8_sub_fp
4390b57cec5SDimitry Andric __kmpc_atomic_float8_sub_rev
4400b57cec5SDimitry Andric __kmpc_atomic_float8_swp
4410b57cec5SDimitry Andric __kmpc_atomic_float8_wr
4420b57cec5SDimitry Andric __kmpc_atomic_float10_add
4430b57cec5SDimitry Andric __kmpc_atomic_float10_add_cpt
4440b57cec5SDimitry Andric __kmpc_atomic_float10_add_fp
4450b57cec5SDimitry Andric __kmpc_atomic_float10_div
4460b57cec5SDimitry Andric __kmpc_atomic_float10_div_cpt
4470b57cec5SDimitry Andric __kmpc_atomic_float10_div_cpt_rev
4480b57cec5SDimitry Andric __kmpc_atomic_float10_div_fp
4490b57cec5SDimitry Andric __kmpc_atomic_float10_div_rev
4500b57cec5SDimitry Andric __kmpc_atomic_float10_mul
4510b57cec5SDimitry Andric __kmpc_atomic_float10_mul_cpt
4520b57cec5SDimitry Andric __kmpc_atomic_float10_mul_fp
4530b57cec5SDimitry Andric __kmpc_atomic_float10_rd
4540b57cec5SDimitry Andric __kmpc_atomic_float10_sub
4550b57cec5SDimitry Andric __kmpc_atomic_float10_sub_cpt
4560b57cec5SDimitry Andric __kmpc_atomic_float10_sub_cpt_rev
4570b57cec5SDimitry Andric __kmpc_atomic_float10_sub_fp
4580b57cec5SDimitry Andric __kmpc_atomic_float10_sub_rev
4590b57cec5SDimitry Andric __kmpc_atomic_float10_swp
4600b57cec5SDimitry Andric __kmpc_atomic_float10_wr
4610b57cec5SDimitry Andric __kmpc_atomic_float16_add
4620b57cec5SDimitry Andric __kmpc_atomic_float16_add_cpt
4630b57cec5SDimitry Andric __kmpc_atomic_float16_div
4640b57cec5SDimitry Andric __kmpc_atomic_float16_div_cpt
4650b57cec5SDimitry Andric __kmpc_atomic_float16_div_cpt_rev
4660b57cec5SDimitry Andric __kmpc_atomic_float16_div_rev
4670b57cec5SDimitry Andric __kmpc_atomic_float16_max
4680b57cec5SDimitry Andric __kmpc_atomic_float16_max_cpt
4690b57cec5SDimitry Andric __kmpc_atomic_float16_min
4700b57cec5SDimitry Andric __kmpc_atomic_float16_min_cpt
4710b57cec5SDimitry Andric __kmpc_atomic_float16_mul
4720b57cec5SDimitry Andric __kmpc_atomic_float16_mul_cpt
4730b57cec5SDimitry Andric __kmpc_atomic_float16_rd
4740b57cec5SDimitry Andric __kmpc_atomic_float16_sub
4750b57cec5SDimitry Andric __kmpc_atomic_float16_sub_cpt
4760b57cec5SDimitry Andric __kmpc_atomic_float16_sub_cpt_rev
4770b57cec5SDimitry Andric __kmpc_atomic_float16_sub_rev
4780b57cec5SDimitry Andric __kmpc_atomic_float16_swp
4790b57cec5SDimitry Andric __kmpc_atomic_float16_wr
4800b57cec5SDimitry Andric @endcode
4810b57cec5SDimitry Andric
4820b57cec5SDimitry Andric Functions for Complex types
4830b57cec5SDimitry Andric ---------------------------
4840b57cec5SDimitry Andric Functions for complex types whose component floating point variables are of size
4850b57cec5SDimitry Andric 4,8,10 or 16 bytes. The names here are based on the size of the component float,
486480093f4SDimitry Andric *not* the size of the complex type. So `__kmpc_atomic_cmplx8_add` is an
487480093f4SDimitry Andric operation on a `complex<double>` or `complex(kind=8)`, *not* `complex<float>`.
4880b57cec5SDimitry Andric
4890b57cec5SDimitry Andric @code
4900b57cec5SDimitry Andric __kmpc_atomic_cmplx4_add
4910b57cec5SDimitry Andric __kmpc_atomic_cmplx4_add_cmplx8
4920b57cec5SDimitry Andric __kmpc_atomic_cmplx4_add_cpt
4930b57cec5SDimitry Andric __kmpc_atomic_cmplx4_div
4940b57cec5SDimitry Andric __kmpc_atomic_cmplx4_div_cmplx8
4950b57cec5SDimitry Andric __kmpc_atomic_cmplx4_div_cpt
4960b57cec5SDimitry Andric __kmpc_atomic_cmplx4_div_cpt_rev
4970b57cec5SDimitry Andric __kmpc_atomic_cmplx4_div_rev
4980b57cec5SDimitry Andric __kmpc_atomic_cmplx4_mul
4990b57cec5SDimitry Andric __kmpc_atomic_cmplx4_mul_cmplx8
5000b57cec5SDimitry Andric __kmpc_atomic_cmplx4_mul_cpt
5010b57cec5SDimitry Andric __kmpc_atomic_cmplx4_rd
5020b57cec5SDimitry Andric __kmpc_atomic_cmplx4_sub
5030b57cec5SDimitry Andric __kmpc_atomic_cmplx4_sub_cmplx8
5040b57cec5SDimitry Andric __kmpc_atomic_cmplx4_sub_cpt
5050b57cec5SDimitry Andric __kmpc_atomic_cmplx4_sub_cpt_rev
5060b57cec5SDimitry Andric __kmpc_atomic_cmplx4_sub_rev
5070b57cec5SDimitry Andric __kmpc_atomic_cmplx4_swp
5080b57cec5SDimitry Andric __kmpc_atomic_cmplx4_wr
5090b57cec5SDimitry Andric __kmpc_atomic_cmplx8_add
5100b57cec5SDimitry Andric __kmpc_atomic_cmplx8_add_cpt
5110b57cec5SDimitry Andric __kmpc_atomic_cmplx8_div
5120b57cec5SDimitry Andric __kmpc_atomic_cmplx8_div_cpt
5130b57cec5SDimitry Andric __kmpc_atomic_cmplx8_div_cpt_rev
5140b57cec5SDimitry Andric __kmpc_atomic_cmplx8_div_rev
5150b57cec5SDimitry Andric __kmpc_atomic_cmplx8_mul
5160b57cec5SDimitry Andric __kmpc_atomic_cmplx8_mul_cpt
5170b57cec5SDimitry Andric __kmpc_atomic_cmplx8_rd
5180b57cec5SDimitry Andric __kmpc_atomic_cmplx8_sub
5190b57cec5SDimitry Andric __kmpc_atomic_cmplx8_sub_cpt
5200b57cec5SDimitry Andric __kmpc_atomic_cmplx8_sub_cpt_rev
5210b57cec5SDimitry Andric __kmpc_atomic_cmplx8_sub_rev
5220b57cec5SDimitry Andric __kmpc_atomic_cmplx8_swp
5230b57cec5SDimitry Andric __kmpc_atomic_cmplx8_wr
5240b57cec5SDimitry Andric __kmpc_atomic_cmplx10_add
5250b57cec5SDimitry Andric __kmpc_atomic_cmplx10_add_cpt
5260b57cec5SDimitry Andric __kmpc_atomic_cmplx10_div
5270b57cec5SDimitry Andric __kmpc_atomic_cmplx10_div_cpt
5280b57cec5SDimitry Andric __kmpc_atomic_cmplx10_div_cpt_rev
5290b57cec5SDimitry Andric __kmpc_atomic_cmplx10_div_rev
5300b57cec5SDimitry Andric __kmpc_atomic_cmplx10_mul
5310b57cec5SDimitry Andric __kmpc_atomic_cmplx10_mul_cpt
5320b57cec5SDimitry Andric __kmpc_atomic_cmplx10_rd
5330b57cec5SDimitry Andric __kmpc_atomic_cmplx10_sub
5340b57cec5SDimitry Andric __kmpc_atomic_cmplx10_sub_cpt
5350b57cec5SDimitry Andric __kmpc_atomic_cmplx10_sub_cpt_rev
5360b57cec5SDimitry Andric __kmpc_atomic_cmplx10_sub_rev
5370b57cec5SDimitry Andric __kmpc_atomic_cmplx10_swp
5380b57cec5SDimitry Andric __kmpc_atomic_cmplx10_wr
5390b57cec5SDimitry Andric __kmpc_atomic_cmplx16_add
5400b57cec5SDimitry Andric __kmpc_atomic_cmplx16_add_cpt
5410b57cec5SDimitry Andric __kmpc_atomic_cmplx16_div
5420b57cec5SDimitry Andric __kmpc_atomic_cmplx16_div_cpt
5430b57cec5SDimitry Andric __kmpc_atomic_cmplx16_div_cpt_rev
5440b57cec5SDimitry Andric __kmpc_atomic_cmplx16_div_rev
5450b57cec5SDimitry Andric __kmpc_atomic_cmplx16_mul
5460b57cec5SDimitry Andric __kmpc_atomic_cmplx16_mul_cpt
5470b57cec5SDimitry Andric __kmpc_atomic_cmplx16_rd
5480b57cec5SDimitry Andric __kmpc_atomic_cmplx16_sub
5490b57cec5SDimitry Andric __kmpc_atomic_cmplx16_sub_cpt
5500b57cec5SDimitry Andric __kmpc_atomic_cmplx16_sub_cpt_rev
5510b57cec5SDimitry Andric __kmpc_atomic_cmplx16_swp
5520b57cec5SDimitry Andric __kmpc_atomic_cmplx16_wr
5530b57cec5SDimitry Andric @endcode
5540b57cec5SDimitry Andric */
5550b57cec5SDimitry Andric
5560b57cec5SDimitry Andric /*!
5570b57cec5SDimitry Andric @ingroup ATOMIC_OPS
5580b57cec5SDimitry Andric @{
5590b57cec5SDimitry Andric */
5600b57cec5SDimitry Andric
5610b57cec5SDimitry Andric /*
5620b57cec5SDimitry Andric * Global vars
5630b57cec5SDimitry Andric */
5640b57cec5SDimitry Andric
5650b57cec5SDimitry Andric #ifndef KMP_GOMP_COMPAT
5660b57cec5SDimitry Andric int __kmp_atomic_mode = 1; // Intel perf
5670b57cec5SDimitry Andric #else
5680b57cec5SDimitry Andric int __kmp_atomic_mode = 2; // GOMP compatibility
5690b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric KMP_ALIGN(128)
5720b57cec5SDimitry Andric
5730b57cec5SDimitry Andric // Control access to all user coded atomics in Gnu compat mode
5740b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock;
5750b57cec5SDimitry Andric // Control access to all user coded atomics for 1-byte fixed data types
5760b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_1i;
5770b57cec5SDimitry Andric // Control access to all user coded atomics for 2-byte fixed data types
5780b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_2i;
5790b57cec5SDimitry Andric // Control access to all user coded atomics for 4-byte fixed data types
5800b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_4i;
5810b57cec5SDimitry Andric // Control access to all user coded atomics for kmp_real32 data type
5820b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_4r;
5830b57cec5SDimitry Andric // Control access to all user coded atomics for 8-byte fixed data types
5840b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_8i;
5850b57cec5SDimitry Andric // Control access to all user coded atomics for kmp_real64 data type
5860b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_8r;
5870b57cec5SDimitry Andric // Control access to all user coded atomics for complex byte data type
5880b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_8c;
5890b57cec5SDimitry Andric // Control access to all user coded atomics for long double data type
5900b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_10r;
5910b57cec5SDimitry Andric // Control access to all user coded atomics for _Quad data type
5920b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_16r;
5930b57cec5SDimitry Andric // Control access to all user coded atomics for double complex data type
5940b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_16c;
5950b57cec5SDimitry Andric // Control access to all user coded atomics for long double complex type
5960b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_20c;
5970b57cec5SDimitry Andric // Control access to all user coded atomics for _Quad complex data type
5980b57cec5SDimitry Andric kmp_atomic_lock_t __kmp_atomic_lock_32c;
5990b57cec5SDimitry Andric
6000b57cec5SDimitry Andric /* 2007-03-02:
6010b57cec5SDimitry Andric Without "volatile" specifier in OP_CMPXCHG and MIN_MAX_CMPXCHG we have a bug
6020b57cec5SDimitry Andric on *_32 and *_32e. This is just a temporary workaround for the problem. It
6030b57cec5SDimitry Andric seems the right solution is writing OP_CMPXCHG and MIN_MAX_CMPXCHG routines
6040b57cec5SDimitry Andric in assembler language. */
6050b57cec5SDimitry Andric #define KMP_ATOMIC_VOLATILE volatile
6060b57cec5SDimitry Andric
6070b57cec5SDimitry Andric #if (KMP_ARCH_X86) && KMP_HAVE_QUAD
6080b57cec5SDimitry Andric
operator +(Quad_a4_t & lhs,Quad_a4_t & rhs)609e8d8bef9SDimitry Andric static inline Quad_a4_t operator+(Quad_a4_t &lhs, Quad_a4_t &rhs) {
610e8d8bef9SDimitry Andric return lhs.q + rhs.q;
6110b57cec5SDimitry Andric }
operator -(Quad_a4_t & lhs,Quad_a4_t & rhs)612e8d8bef9SDimitry Andric static inline Quad_a4_t operator-(Quad_a4_t &lhs, Quad_a4_t &rhs) {
613e8d8bef9SDimitry Andric return lhs.q - rhs.q;
6140b57cec5SDimitry Andric }
operator *(Quad_a4_t & lhs,Quad_a4_t & rhs)615e8d8bef9SDimitry Andric static inline Quad_a4_t operator*(Quad_a4_t &lhs, Quad_a4_t &rhs) {
616e8d8bef9SDimitry Andric return lhs.q * rhs.q;
6170b57cec5SDimitry Andric }
operator /(Quad_a4_t & lhs,Quad_a4_t & rhs)618e8d8bef9SDimitry Andric static inline Quad_a4_t operator/(Quad_a4_t &lhs, Quad_a4_t &rhs) {
619e8d8bef9SDimitry Andric return lhs.q / rhs.q;
6200b57cec5SDimitry Andric }
operator <(Quad_a4_t & lhs,Quad_a4_t & rhs)6210b57cec5SDimitry Andric static inline bool operator<(Quad_a4_t &lhs, Quad_a4_t &rhs) {
6220b57cec5SDimitry Andric return lhs.q < rhs.q;
6230b57cec5SDimitry Andric }
operator >(Quad_a4_t & lhs,Quad_a4_t & rhs)6240b57cec5SDimitry Andric static inline bool operator>(Quad_a4_t &lhs, Quad_a4_t &rhs) {
6250b57cec5SDimitry Andric return lhs.q > rhs.q;
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric
operator +(Quad_a16_t & lhs,Quad_a16_t & rhs)628e8d8bef9SDimitry Andric static inline Quad_a16_t operator+(Quad_a16_t &lhs, Quad_a16_t &rhs) {
629e8d8bef9SDimitry Andric return lhs.q + rhs.q;
6300b57cec5SDimitry Andric }
operator -(Quad_a16_t & lhs,Quad_a16_t & rhs)631e8d8bef9SDimitry Andric static inline Quad_a16_t operator-(Quad_a16_t &lhs, Quad_a16_t &rhs) {
632e8d8bef9SDimitry Andric return lhs.q - rhs.q;
6330b57cec5SDimitry Andric }
operator *(Quad_a16_t & lhs,Quad_a16_t & rhs)634e8d8bef9SDimitry Andric static inline Quad_a16_t operator*(Quad_a16_t &lhs, Quad_a16_t &rhs) {
635e8d8bef9SDimitry Andric return lhs.q * rhs.q;
6360b57cec5SDimitry Andric }
operator /(Quad_a16_t & lhs,Quad_a16_t & rhs)637e8d8bef9SDimitry Andric static inline Quad_a16_t operator/(Quad_a16_t &lhs, Quad_a16_t &rhs) {
638e8d8bef9SDimitry Andric return lhs.q / rhs.q;
6390b57cec5SDimitry Andric }
operator <(Quad_a16_t & lhs,Quad_a16_t & rhs)6400b57cec5SDimitry Andric static inline bool operator<(Quad_a16_t &lhs, Quad_a16_t &rhs) {
6410b57cec5SDimitry Andric return lhs.q < rhs.q;
6420b57cec5SDimitry Andric }
operator >(Quad_a16_t & lhs,Quad_a16_t & rhs)6430b57cec5SDimitry Andric static inline bool operator>(Quad_a16_t &lhs, Quad_a16_t &rhs) {
6440b57cec5SDimitry Andric return lhs.q > rhs.q;
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric
operator +(kmp_cmplx128_a4_t & lhs,kmp_cmplx128_a4_t & rhs)647e8d8bef9SDimitry Andric static inline kmp_cmplx128_a4_t operator+(kmp_cmplx128_a4_t &lhs,
648e8d8bef9SDimitry Andric kmp_cmplx128_a4_t &rhs) {
649e8d8bef9SDimitry Andric return lhs.q + rhs.q;
6500b57cec5SDimitry Andric }
operator -(kmp_cmplx128_a4_t & lhs,kmp_cmplx128_a4_t & rhs)651e8d8bef9SDimitry Andric static inline kmp_cmplx128_a4_t operator-(kmp_cmplx128_a4_t &lhs,
652e8d8bef9SDimitry Andric kmp_cmplx128_a4_t &rhs) {
653e8d8bef9SDimitry Andric return lhs.q - rhs.q;
6540b57cec5SDimitry Andric }
operator *(kmp_cmplx128_a4_t & lhs,kmp_cmplx128_a4_t & rhs)655e8d8bef9SDimitry Andric static inline kmp_cmplx128_a4_t operator*(kmp_cmplx128_a4_t &lhs,
656e8d8bef9SDimitry Andric kmp_cmplx128_a4_t &rhs) {
657e8d8bef9SDimitry Andric return lhs.q * rhs.q;
6580b57cec5SDimitry Andric }
operator /(kmp_cmplx128_a4_t & lhs,kmp_cmplx128_a4_t & rhs)659e8d8bef9SDimitry Andric static inline kmp_cmplx128_a4_t operator/(kmp_cmplx128_a4_t &lhs,
660e8d8bef9SDimitry Andric kmp_cmplx128_a4_t &rhs) {
661e8d8bef9SDimitry Andric return lhs.q / rhs.q;
6620b57cec5SDimitry Andric }
6630b57cec5SDimitry Andric
operator +(kmp_cmplx128_a16_t & lhs,kmp_cmplx128_a16_t & rhs)664e8d8bef9SDimitry Andric static inline kmp_cmplx128_a16_t operator+(kmp_cmplx128_a16_t &lhs,
6650b57cec5SDimitry Andric kmp_cmplx128_a16_t &rhs) {
666e8d8bef9SDimitry Andric return lhs.q + rhs.q;
6670b57cec5SDimitry Andric }
operator -(kmp_cmplx128_a16_t & lhs,kmp_cmplx128_a16_t & rhs)668e8d8bef9SDimitry Andric static inline kmp_cmplx128_a16_t operator-(kmp_cmplx128_a16_t &lhs,
6690b57cec5SDimitry Andric kmp_cmplx128_a16_t &rhs) {
670e8d8bef9SDimitry Andric return lhs.q - rhs.q;
6710b57cec5SDimitry Andric }
operator *(kmp_cmplx128_a16_t & lhs,kmp_cmplx128_a16_t & rhs)672e8d8bef9SDimitry Andric static inline kmp_cmplx128_a16_t operator*(kmp_cmplx128_a16_t &lhs,
6730b57cec5SDimitry Andric kmp_cmplx128_a16_t &rhs) {
674e8d8bef9SDimitry Andric return lhs.q * rhs.q;
6750b57cec5SDimitry Andric }
operator /(kmp_cmplx128_a16_t & lhs,kmp_cmplx128_a16_t & rhs)676e8d8bef9SDimitry Andric static inline kmp_cmplx128_a16_t operator/(kmp_cmplx128_a16_t &lhs,
6770b57cec5SDimitry Andric kmp_cmplx128_a16_t &rhs) {
678e8d8bef9SDimitry Andric return lhs.q / rhs.q;
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric
6810b57cec5SDimitry Andric #endif // (KMP_ARCH_X86) && KMP_HAVE_QUAD
6820b57cec5SDimitry Andric
6830b57cec5SDimitry Andric // ATOMIC implementation routines -----------------------------------------
6840b57cec5SDimitry Andric // One routine for each operation and operand type.
6850b57cec5SDimitry Andric // All routines declarations looks like
6860b57cec5SDimitry Andric // void __kmpc_atomic_RTYPE_OP( ident_t*, int, TYPE *lhs, TYPE rhs );
6870b57cec5SDimitry Andric
6880b57cec5SDimitry Andric #define KMP_CHECK_GTID \
6890b57cec5SDimitry Andric if (gtid == KMP_GTID_UNKNOWN) { \
6900b57cec5SDimitry Andric gtid = __kmp_entry_gtid(); \
6910b57cec5SDimitry Andric } // check and get gtid when needed
6920b57cec5SDimitry Andric
6930b57cec5SDimitry Andric // Beginning of a definition (provides name, parameters, gebug trace)
6940b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned
6950b57cec5SDimitry Andric // fixed)
6960b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
6970b57cec5SDimitry Andric // TYPE - operands' type
6980b57cec5SDimitry Andric #define ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, RET_TYPE) \
6990b57cec5SDimitry Andric RET_TYPE __kmpc_atomic_##TYPE_ID##_##OP_ID(ident_t *id_ref, int gtid, \
7000b57cec5SDimitry Andric TYPE *lhs, TYPE rhs) { \
7010b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
7020b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID ": T#%d\n", gtid));
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andric // ------------------------------------------------------------------------
7050b57cec5SDimitry Andric // Lock variables used for critical sections for various size operands
7060b57cec5SDimitry Andric #define ATOMIC_LOCK0 __kmp_atomic_lock // all types, for Gnu compat
7070b57cec5SDimitry Andric #define ATOMIC_LOCK1i __kmp_atomic_lock_1i // char
7080b57cec5SDimitry Andric #define ATOMIC_LOCK2i __kmp_atomic_lock_2i // short
7090b57cec5SDimitry Andric #define ATOMIC_LOCK4i __kmp_atomic_lock_4i // long int
7100b57cec5SDimitry Andric #define ATOMIC_LOCK4r __kmp_atomic_lock_4r // float
7110b57cec5SDimitry Andric #define ATOMIC_LOCK8i __kmp_atomic_lock_8i // long long int
7120b57cec5SDimitry Andric #define ATOMIC_LOCK8r __kmp_atomic_lock_8r // double
7130b57cec5SDimitry Andric #define ATOMIC_LOCK8c __kmp_atomic_lock_8c // float complex
7140b57cec5SDimitry Andric #define ATOMIC_LOCK10r __kmp_atomic_lock_10r // long double
7150b57cec5SDimitry Andric #define ATOMIC_LOCK16r __kmp_atomic_lock_16r // _Quad
7160b57cec5SDimitry Andric #define ATOMIC_LOCK16c __kmp_atomic_lock_16c // double complex
7170b57cec5SDimitry Andric #define ATOMIC_LOCK20c __kmp_atomic_lock_20c // long double complex
7180b57cec5SDimitry Andric #define ATOMIC_LOCK32c __kmp_atomic_lock_32c // _Quad complex
7190b57cec5SDimitry Andric
7200b57cec5SDimitry Andric // ------------------------------------------------------------------------
7210b57cec5SDimitry Andric // Operation on *lhs, rhs bound by critical section
7220b57cec5SDimitry Andric // OP - operator (it's supposed to contain an assignment)
7230b57cec5SDimitry Andric // LCK_ID - lock identifier
7240b57cec5SDimitry Andric // Note: don't check gtid as it should always be valid
7250b57cec5SDimitry Andric // 1, 2-byte - expect valid parameter, other - check before this macro
7260b57cec5SDimitry Andric #define OP_CRITICAL(OP, LCK_ID) \
7270b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
7280b57cec5SDimitry Andric \
7290b57cec5SDimitry Andric (*lhs) OP(rhs); \
7300b57cec5SDimitry Andric \
7310b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
7320b57cec5SDimitry Andric
733e8d8bef9SDimitry Andric #define OP_UPDATE_CRITICAL(TYPE, OP, LCK_ID) \
734e8d8bef9SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
735349cc55cSDimitry Andric (*lhs) = (TYPE)((*lhs)OP rhs); \
736e8d8bef9SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
737e8d8bef9SDimitry Andric
7380b57cec5SDimitry Andric // ------------------------------------------------------------------------
7390b57cec5SDimitry Andric // For GNU compatibility, we may need to use a critical section,
7400b57cec5SDimitry Andric // even though it is not required by the ISA.
7410b57cec5SDimitry Andric //
7420b57cec5SDimitry Andric // On IA-32 architecture, all atomic operations except for fixed 4 byte add,
7430b57cec5SDimitry Andric // sub, and bitwise logical ops, and 1 & 2 byte logical ops use a common
7440b57cec5SDimitry Andric // critical section. On Intel(R) 64, all atomic operations are done with fetch
7450b57cec5SDimitry Andric // and add or compare and exchange. Therefore, the FLAG parameter to this
7460b57cec5SDimitry Andric // macro is either KMP_ARCH_X86 or 0 (or 1, for Intel-specific extension which
7470b57cec5SDimitry Andric // require a critical section, where we predict that they will be implemented
7480b57cec5SDimitry Andric // in the Gnu codegen by calling GOMP_atomic_start() / GOMP_atomic_end()).
7490b57cec5SDimitry Andric //
7500b57cec5SDimitry Andric // When the OP_GOMP_CRITICAL macro is used in a *CRITICAL* macro construct,
7510b57cec5SDimitry Andric // the FLAG parameter should always be 1. If we know that we will be using
7520b57cec5SDimitry Andric // a critical section, then we want to make certain that we use the generic
7530b57cec5SDimitry Andric // lock __kmp_atomic_lock to protect the atomic update, and not of of the
7540b57cec5SDimitry Andric // locks that are specialized based upon the size or type of the data.
7550b57cec5SDimitry Andric //
7560b57cec5SDimitry Andric // If FLAG is 0, then we are relying on dead code elimination by the build
7570b57cec5SDimitry Andric // compiler to get rid of the useless block of code, and save a needless
7580b57cec5SDimitry Andric // branch at runtime.
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
7610b57cec5SDimitry Andric #define OP_GOMP_CRITICAL(OP, FLAG) \
7620b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
7630b57cec5SDimitry Andric KMP_CHECK_GTID; \
7640b57cec5SDimitry Andric OP_CRITICAL(OP, 0); \
7650b57cec5SDimitry Andric return; \
7660b57cec5SDimitry Andric }
767e8d8bef9SDimitry Andric
768e8d8bef9SDimitry Andric #define OP_UPDATE_GOMP_CRITICAL(TYPE, OP, FLAG) \
769e8d8bef9SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
770e8d8bef9SDimitry Andric KMP_CHECK_GTID; \
771e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, 0); \
772e8d8bef9SDimitry Andric return; \
773e8d8bef9SDimitry Andric }
7740b57cec5SDimitry Andric #else
7750b57cec5SDimitry Andric #define OP_GOMP_CRITICAL(OP, FLAG)
776e8d8bef9SDimitry Andric #define OP_UPDATE_GOMP_CRITICAL(TYPE, OP, FLAG)
7770b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
7780b57cec5SDimitry Andric
7790b57cec5SDimitry Andric #if KMP_MIC
7800b57cec5SDimitry Andric #define KMP_DO_PAUSE _mm_delay_32(1)
7810b57cec5SDimitry Andric #else
782fe6060f1SDimitry Andric #define KMP_DO_PAUSE
7830b57cec5SDimitry Andric #endif /* KMP_MIC */
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric // ------------------------------------------------------------------------
7860b57cec5SDimitry Andric // Operation on *lhs, rhs using "compare_and_store" routine
7870b57cec5SDimitry Andric // TYPE - operands' type
7880b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
7890b57cec5SDimitry Andric // OP - operator
7900b57cec5SDimitry Andric #define OP_CMPXCHG(TYPE, BITS, OP) \
7910b57cec5SDimitry Andric { \
7920b57cec5SDimitry Andric TYPE old_value, new_value; \
7930b57cec5SDimitry Andric old_value = *(TYPE volatile *)lhs; \
794349cc55cSDimitry Andric new_value = (TYPE)(old_value OP rhs); \
7950b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
7960b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
7970b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & new_value)) { \
7980b57cec5SDimitry Andric KMP_DO_PAUSE; \
7990b57cec5SDimitry Andric \
8000b57cec5SDimitry Andric old_value = *(TYPE volatile *)lhs; \
801349cc55cSDimitry Andric new_value = (TYPE)(old_value OP rhs); \
8020b57cec5SDimitry Andric } \
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric
8050b57cec5SDimitry Andric #if USE_CMPXCHG_FIX
8060b57cec5SDimitry Andric // 2007-06-25:
8070b57cec5SDimitry Andric // workaround for C78287 (complex(kind=4) data type). lin_32, lin_32e, win_32
8080b57cec5SDimitry Andric // and win_32e are affected (I verified the asm). Compiler ignores the volatile
8090b57cec5SDimitry Andric // qualifier of the temp_val in the OP_CMPXCHG macro. This is a problem of the
8100b57cec5SDimitry Andric // compiler. Related tracker is C76005, targeted to 11.0. I verified the asm of
8110b57cec5SDimitry Andric // the workaround.
8120b57cec5SDimitry Andric #define OP_CMPXCHG_WORKAROUND(TYPE, BITS, OP) \
8130b57cec5SDimitry Andric { \
8140b57cec5SDimitry Andric struct _sss { \
8150b57cec5SDimitry Andric TYPE cmp; \
8160b57cec5SDimitry Andric kmp_int##BITS *vvv; \
8170b57cec5SDimitry Andric }; \
8180b57cec5SDimitry Andric struct _sss old_value, new_value; \
8190b57cec5SDimitry Andric old_value.vvv = (kmp_int##BITS *)&old_value.cmp; \
8200b57cec5SDimitry Andric new_value.vvv = (kmp_int##BITS *)&new_value.cmp; \
8210b57cec5SDimitry Andric *old_value.vvv = *(volatile kmp_int##BITS *)lhs; \
822e8d8bef9SDimitry Andric new_value.cmp = (TYPE)(old_value.cmp OP rhs); \
8230b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
8240b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) old_value.vvv, \
8250b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) new_value.vvv)) { \
8260b57cec5SDimitry Andric KMP_DO_PAUSE; \
8270b57cec5SDimitry Andric \
8280b57cec5SDimitry Andric *old_value.vvv = *(volatile kmp_int##BITS *)lhs; \
829e8d8bef9SDimitry Andric new_value.cmp = (TYPE)(old_value.cmp OP rhs); \
8300b57cec5SDimitry Andric } \
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric // end of the first part of the workaround for C78287
8330b57cec5SDimitry Andric #endif // USE_CMPXCHG_FIX
8340b57cec5SDimitry Andric
835*bdd1243dSDimitry Andric #if KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM)
836fe6060f1SDimitry Andric // Undo explicit type casts to get MSVC ARM64 to build. Uses
837fe6060f1SDimitry Andric // OP_CMPXCHG_WORKAROUND definition for OP_CMPXCHG
838fe6060f1SDimitry Andric #undef OP_CMPXCHG
839fe6060f1SDimitry Andric #define OP_CMPXCHG(TYPE, BITS, OP) \
840fe6060f1SDimitry Andric { \
841fe6060f1SDimitry Andric struct _sss { \
842fe6060f1SDimitry Andric TYPE cmp; \
843fe6060f1SDimitry Andric kmp_int##BITS *vvv; \
844fe6060f1SDimitry Andric }; \
845fe6060f1SDimitry Andric struct _sss old_value, new_value; \
846fe6060f1SDimitry Andric old_value.vvv = (kmp_int##BITS *)&old_value.cmp; \
847fe6060f1SDimitry Andric new_value.vvv = (kmp_int##BITS *)&new_value.cmp; \
848fe6060f1SDimitry Andric *old_value.vvv = *(volatile kmp_int##BITS *)lhs; \
849fe6060f1SDimitry Andric new_value.cmp = old_value.cmp OP rhs; \
850fe6060f1SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
851fe6060f1SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) old_value.vvv, \
852fe6060f1SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) new_value.vvv)) { \
853fe6060f1SDimitry Andric KMP_DO_PAUSE; \
854fe6060f1SDimitry Andric \
855fe6060f1SDimitry Andric *old_value.vvv = *(volatile kmp_int##BITS *)lhs; \
856fe6060f1SDimitry Andric new_value.cmp = old_value.cmp OP rhs; \
857fe6060f1SDimitry Andric } \
858fe6060f1SDimitry Andric }
859fe6060f1SDimitry Andric
860fe6060f1SDimitry Andric #undef OP_UPDATE_CRITICAL
861fe6060f1SDimitry Andric #define OP_UPDATE_CRITICAL(TYPE, OP, LCK_ID) \
862fe6060f1SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
863fe6060f1SDimitry Andric (*lhs) = (*lhs)OP rhs; \
864fe6060f1SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
865fe6060f1SDimitry Andric
866*bdd1243dSDimitry Andric #endif // KMP_OS_WINDOWS && (KMP_ARCH_AARCH64 || KMP_ARCH_ARM)
867fe6060f1SDimitry Andric
8680b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
8690b57cec5SDimitry Andric
8700b57cec5SDimitry Andric // ------------------------------------------------------------------------
8710b57cec5SDimitry Andric // X86 or X86_64: no alignment problems ====================================
8720b57cec5SDimitry Andric #define ATOMIC_FIXED_ADD(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
8730b57cec5SDimitry Andric GOMP_FLAG) \
8740b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
875e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
8760b57cec5SDimitry Andric /* OP used as a sign for subtraction: (lhs-rhs) --> (lhs+-rhs) */ \
8770b57cec5SDimitry Andric KMP_TEST_THEN_ADD##BITS(lhs, OP rhs); \
8780b57cec5SDimitry Andric }
8790b57cec5SDimitry Andric // -------------------------------------------------------------------------
8800b57cec5SDimitry Andric #define ATOMIC_CMPXCHG(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
8810b57cec5SDimitry Andric GOMP_FLAG) \
8820b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
883e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
8840b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) \
8850b57cec5SDimitry Andric }
8860b57cec5SDimitry Andric #if USE_CMPXCHG_FIX
8870b57cec5SDimitry Andric // -------------------------------------------------------------------------
8880b57cec5SDimitry Andric // workaround for C78287 (complex(kind=4) data type)
8890b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_WORKAROUND(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, \
8900b57cec5SDimitry Andric MASK, GOMP_FLAG) \
8910b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
892e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
8930b57cec5SDimitry Andric OP_CMPXCHG_WORKAROUND(TYPE, BITS, OP) \
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric // end of the second part of the workaround for C78287
8960b57cec5SDimitry Andric #endif // USE_CMPXCHG_FIX
8970b57cec5SDimitry Andric
8980b57cec5SDimitry Andric #else
8990b57cec5SDimitry Andric // -------------------------------------------------------------------------
9000b57cec5SDimitry Andric // Code for other architectures that don't handle unaligned accesses.
9010b57cec5SDimitry Andric #define ATOMIC_FIXED_ADD(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
9020b57cec5SDimitry Andric GOMP_FLAG) \
9030b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
904e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
9050b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
9060b57cec5SDimitry Andric /* OP used as a sign for subtraction: (lhs-rhs) --> (lhs+-rhs) */ \
9070b57cec5SDimitry Andric KMP_TEST_THEN_ADD##BITS(lhs, OP rhs); \
9080b57cec5SDimitry Andric } else { \
9090b57cec5SDimitry Andric KMP_CHECK_GTID; \
910e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, \
911e8d8bef9SDimitry Andric LCK_ID) /* unaligned address - use critical */ \
9120b57cec5SDimitry Andric } \
9130b57cec5SDimitry Andric }
9140b57cec5SDimitry Andric // -------------------------------------------------------------------------
9150b57cec5SDimitry Andric #define ATOMIC_CMPXCHG(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
9160b57cec5SDimitry Andric GOMP_FLAG) \
9170b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
918e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
9190b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
9200b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
9210b57cec5SDimitry Andric } else { \
9220b57cec5SDimitry Andric KMP_CHECK_GTID; \
923e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, \
924e8d8bef9SDimitry Andric LCK_ID) /* unaligned address - use critical */ \
9250b57cec5SDimitry Andric } \
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric #if USE_CMPXCHG_FIX
9280b57cec5SDimitry Andric // -------------------------------------------------------------------------
9290b57cec5SDimitry Andric // workaround for C78287 (complex(kind=4) data type)
9300b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_WORKAROUND(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, \
9310b57cec5SDimitry Andric MASK, GOMP_FLAG) \
9320b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
933e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
9340b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
9350b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
9360b57cec5SDimitry Andric } else { \
9370b57cec5SDimitry Andric KMP_CHECK_GTID; \
938e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, \
939e8d8bef9SDimitry Andric LCK_ID) /* unaligned address - use critical */ \
9400b57cec5SDimitry Andric } \
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric // end of the second part of the workaround for C78287
9430b57cec5SDimitry Andric #endif // USE_CMPXCHG_FIX
9440b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric // Routines for ATOMIC 4-byte operands addition and subtraction
9470b57cec5SDimitry Andric ATOMIC_FIXED_ADD(fixed4, add, kmp_int32, 32, +, 4i, 3,
9480b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_add
9490b57cec5SDimitry Andric ATOMIC_FIXED_ADD(fixed4, sub, kmp_int32, 32, -, 4i, 3,
9500b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_sub
9510b57cec5SDimitry Andric
9520b57cec5SDimitry Andric ATOMIC_CMPXCHG(float4, add, kmp_real32, 32, +, 4r, 3,
9530b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_add
9540b57cec5SDimitry Andric ATOMIC_CMPXCHG(float4, sub, kmp_real32, 32, -, 4r, 3,
9550b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andric // Routines for ATOMIC 8-byte operands addition and subtraction
9580b57cec5SDimitry Andric ATOMIC_FIXED_ADD(fixed8, add, kmp_int64, 64, +, 8i, 7,
9590b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_add
9600b57cec5SDimitry Andric ATOMIC_FIXED_ADD(fixed8, sub, kmp_int64, 64, -, 8i, 7,
9610b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub
9620b57cec5SDimitry Andric
9630b57cec5SDimitry Andric ATOMIC_CMPXCHG(float8, add, kmp_real64, 64, +, 8r, 7,
9640b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_add
9650b57cec5SDimitry Andric ATOMIC_CMPXCHG(float8, sub, kmp_real64, 64, -, 8r, 7,
9660b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub
9670b57cec5SDimitry Andric
9680b57cec5SDimitry Andric // ------------------------------------------------------------------------
9690b57cec5SDimitry Andric // Entries definition for integer operands
9700b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed4, float4)
9710b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
9720b57cec5SDimitry Andric // TYPE - operand type
9730b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
9740b57cec5SDimitry Andric // OP - operator (used in critical section)
9750b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
9760b57cec5SDimitry Andric // MASK - used for alignment check
9770b57cec5SDimitry Andric
9780b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, BITS,OP,LCK_ID,MASK,GOMP_FLAG
9790b57cec5SDimitry Andric // ------------------------------------------------------------------------
9800b57cec5SDimitry Andric // Routines for ATOMIC integer operands, other operators
9810b57cec5SDimitry Andric // ------------------------------------------------------------------------
9820b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG
9830b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, add, kmp_int8, 8, +, 1i, 0,
9840b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_add
9850b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, andb, kmp_int8, 8, &, 1i, 0,
9860b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed1_andb
9870b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, div, kmp_int8, 8, /, 1i, 0,
9880b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div
9890b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1u, div, kmp_uint8, 8, /, 1i, 0,
9900b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div
9910b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, mul, kmp_int8, 8, *, 1i, 0,
9920b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul
9930b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, orb, kmp_int8, 8, |, 1i, 0,
9940b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed1_orb
9950b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, shl, kmp_int8, 8, <<, 1i, 0,
9960b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shl
9970b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, shr, kmp_int8, 8, >>, 1i, 0,
9980b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shr
9990b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1u, shr, kmp_uint8, 8, >>, 1i, 0,
10000b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_shr
10010b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, sub, kmp_int8, 8, -, 1i, 0,
10020b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub
10030b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, xor, kmp_int8, 8, ^, 1i, 0,
10040b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed1_xor
10050b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, add, kmp_int16, 16, +, 2i, 1,
10060b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_add
10070b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, andb, kmp_int16, 16, &, 2i, 1,
10080b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed2_andb
10090b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, div, kmp_int16, 16, /, 2i, 1,
10100b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div
10110b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2u, div, kmp_uint16, 16, /, 2i, 1,
10120b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div
10130b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, mul, kmp_int16, 16, *, 2i, 1,
10140b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul
10150b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, orb, kmp_int16, 16, |, 2i, 1,
10160b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed2_orb
10170b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, shl, kmp_int16, 16, <<, 2i, 1,
10180b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shl
10190b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, shr, kmp_int16, 16, >>, 2i, 1,
10200b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shr
10210b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2u, shr, kmp_uint16, 16, >>, 2i, 1,
10220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_shr
10230b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, sub, kmp_int16, 16, -, 2i, 1,
10240b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub
10250b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, xor, kmp_int16, 16, ^, 2i, 1,
10260b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed2_xor
10270b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, andb, kmp_int32, 32, &, 4i, 3,
10280b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_andb
10290b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, div, kmp_int32, 32, /, 4i, 3,
10300b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_div
10310b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4u, div, kmp_uint32, 32, /, 4i, 3,
10320b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_div
10330b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, mul, kmp_int32, 32, *, 4i, 3,
10340b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_mul
10350b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, orb, kmp_int32, 32, |, 4i, 3,
10360b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_orb
10370b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, shl, kmp_int32, 32, <<, 4i, 3,
10380b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shl
10390b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, shr, kmp_int32, 32, >>, 4i, 3,
10400b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shr
10410b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4u, shr, kmp_uint32, 32, >>, 4i, 3,
10420b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_shr
10430b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, xor, kmp_int32, 32, ^, 4i, 3,
10440b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_xor
10450b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, andb, kmp_int64, 64, &, 8i, 7,
10460b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_andb
10470b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, div, kmp_int64, 64, /, 8i, 7,
10480b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div
10490b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8u, div, kmp_uint64, 64, /, 8i, 7,
10500b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div
10510b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, mul, kmp_int64, 64, *, 8i, 7,
10520b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul
10530b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, orb, kmp_int64, 64, |, 8i, 7,
10540b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_orb
10550b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, shl, kmp_int64, 64, <<, 8i, 7,
10560b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shl
10570b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, shr, kmp_int64, 64, >>, 8i, 7,
10580b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shr
10590b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8u, shr, kmp_uint64, 64, >>, 8i, 7,
10600b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_shr
10610b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, xor, kmp_int64, 64, ^, 8i, 7,
10620b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_xor
10630b57cec5SDimitry Andric ATOMIC_CMPXCHG(float4, div, kmp_real32, 32, /, 4r, 3,
10640b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div
10650b57cec5SDimitry Andric ATOMIC_CMPXCHG(float4, mul, kmp_real32, 32, *, 4r, 3,
10660b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_mul
10670b57cec5SDimitry Andric ATOMIC_CMPXCHG(float8, div, kmp_real64, 64, /, 8r, 7,
10680b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div
10690b57cec5SDimitry Andric ATOMIC_CMPXCHG(float8, mul, kmp_real64, 64, *, 8r, 7,
10700b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_mul
10710b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG
10720b57cec5SDimitry Andric
10730b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
10740b57cec5SDimitry Andric /* Routines for C/C++ Reduction operators && and || */
10750b57cec5SDimitry Andric
10760b57cec5SDimitry Andric // ------------------------------------------------------------------------
10770b57cec5SDimitry Andric // Need separate macros for &&, || because there is no combined assignment
10780b57cec5SDimitry Andric // TODO: eliminate ATOMIC_CRIT_{L,EQV} macros as not used
10790b57cec5SDimitry Andric #define ATOMIC_CRIT_L(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
10800b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
10810b57cec5SDimitry Andric OP_GOMP_CRITICAL(= *lhs OP, GOMP_FLAG) \
10820b57cec5SDimitry Andric OP_CRITICAL(= *lhs OP, LCK_ID) \
10830b57cec5SDimitry Andric }
10840b57cec5SDimitry Andric
10850b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
10860b57cec5SDimitry Andric
10870b57cec5SDimitry Andric // ------------------------------------------------------------------------
10880b57cec5SDimitry Andric // X86 or X86_64: no alignment problems ===================================
10890b57cec5SDimitry Andric #define ATOMIC_CMPX_L(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, GOMP_FLAG) \
10900b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
10910b57cec5SDimitry Andric OP_GOMP_CRITICAL(= *lhs OP, GOMP_FLAG) \
10920b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) \
10930b57cec5SDimitry Andric }
10940b57cec5SDimitry Andric
10950b57cec5SDimitry Andric #else
10960b57cec5SDimitry Andric // ------------------------------------------------------------------------
10970b57cec5SDimitry Andric // Code for other architectures that don't handle unaligned accesses.
10980b57cec5SDimitry Andric #define ATOMIC_CMPX_L(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, GOMP_FLAG) \
10990b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
11000b57cec5SDimitry Andric OP_GOMP_CRITICAL(= *lhs OP, GOMP_FLAG) \
11010b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
11020b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
11030b57cec5SDimitry Andric } else { \
11040b57cec5SDimitry Andric KMP_CHECK_GTID; \
11050b57cec5SDimitry Andric OP_CRITICAL(= *lhs OP, LCK_ID) /* unaligned - use critical */ \
11060b57cec5SDimitry Andric } \
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
11090b57cec5SDimitry Andric
11100b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed1, andl, char, 8, &&, 1i, 0,
11110b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_andl
11120b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed1, orl, char, 8, ||, 1i, 0,
11130b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_orl
11140b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed2, andl, short, 16, &&, 2i, 1,
11150b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_andl
11160b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed2, orl, short, 16, ||, 2i, 1,
11170b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_orl
11180b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed4, andl, kmp_int32, 32, &&, 4i, 3,
11190b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_andl
11200b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed4, orl, kmp_int32, 32, ||, 4i, 3,
11210b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_orl
11220b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed8, andl, kmp_int64, 64, &&, 8i, 7,
11230b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_andl
11240b57cec5SDimitry Andric ATOMIC_CMPX_L(fixed8, orl, kmp_int64, 64, ||, 8i, 7,
11250b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_orl
11260b57cec5SDimitry Andric
11270b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
11280b57cec5SDimitry Andric /* Routines for Fortran operators that matched no one in C: */
11290b57cec5SDimitry Andric /* MAX, MIN, .EQV., .NEQV. */
11300b57cec5SDimitry Andric /* Operators .AND., .OR. are covered by __kmpc_atomic_*_{andl,orl} */
11310b57cec5SDimitry Andric /* Intrinsics IAND, IOR, IEOR are covered by __kmpc_atomic_*_{andb,orb,xor} */
11320b57cec5SDimitry Andric
11330b57cec5SDimitry Andric // -------------------------------------------------------------------------
11340b57cec5SDimitry Andric // MIN and MAX need separate macros
11350b57cec5SDimitry Andric // OP - operator to check if we need any actions?
11360b57cec5SDimitry Andric #define MIN_MAX_CRITSECT(OP, LCK_ID) \
11370b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
11380b57cec5SDimitry Andric \
11390b57cec5SDimitry Andric if (*lhs OP rhs) { /* still need actions? */ \
11400b57cec5SDimitry Andric *lhs = rhs; \
11410b57cec5SDimitry Andric } \
11420b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
11430b57cec5SDimitry Andric
11440b57cec5SDimitry Andric // -------------------------------------------------------------------------
11450b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
11460b57cec5SDimitry Andric #define GOMP_MIN_MAX_CRITSECT(OP, FLAG) \
11470b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
11480b57cec5SDimitry Andric KMP_CHECK_GTID; \
11490b57cec5SDimitry Andric MIN_MAX_CRITSECT(OP, 0); \
11500b57cec5SDimitry Andric return; \
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric #else
11530b57cec5SDimitry Andric #define GOMP_MIN_MAX_CRITSECT(OP, FLAG)
11540b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andric // -------------------------------------------------------------------------
11570b57cec5SDimitry Andric #define MIN_MAX_CMPXCHG(TYPE, BITS, OP) \
11580b57cec5SDimitry Andric { \
11590b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
11600b57cec5SDimitry Andric TYPE old_value; \
11610b57cec5SDimitry Andric temp_val = *lhs; \
11620b57cec5SDimitry Andric old_value = temp_val; \
11630b57cec5SDimitry Andric while (old_value OP rhs && /* still need actions? */ \
11640b57cec5SDimitry Andric !KMP_COMPARE_AND_STORE_ACQ##BITS( \
11650b57cec5SDimitry Andric (kmp_int##BITS *)lhs, \
11660b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
11670b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & rhs)) { \
11680b57cec5SDimitry Andric temp_val = *lhs; \
11690b57cec5SDimitry Andric old_value = temp_val; \
11700b57cec5SDimitry Andric } \
11710b57cec5SDimitry Andric }
11720b57cec5SDimitry Andric
11730b57cec5SDimitry Andric // -------------------------------------------------------------------------
11740b57cec5SDimitry Andric // 1-byte, 2-byte operands - use critical section
11750b57cec5SDimitry Andric #define MIN_MAX_CRITICAL(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
11760b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
11770b57cec5SDimitry Andric if (*lhs OP rhs) { /* need actions? */ \
11780b57cec5SDimitry Andric GOMP_MIN_MAX_CRITSECT(OP, GOMP_FLAG) \
11790b57cec5SDimitry Andric MIN_MAX_CRITSECT(OP, LCK_ID) \
11800b57cec5SDimitry Andric } \
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric
11830b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
11840b57cec5SDimitry Andric
11850b57cec5SDimitry Andric // -------------------------------------------------------------------------
11860b57cec5SDimitry Andric // X86 or X86_64: no alignment problems ====================================
11870b57cec5SDimitry Andric #define MIN_MAX_COMPXCHG(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
11880b57cec5SDimitry Andric GOMP_FLAG) \
11890b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
11900b57cec5SDimitry Andric if (*lhs OP rhs) { \
11910b57cec5SDimitry Andric GOMP_MIN_MAX_CRITSECT(OP, GOMP_FLAG) \
11920b57cec5SDimitry Andric MIN_MAX_CMPXCHG(TYPE, BITS, OP) \
11930b57cec5SDimitry Andric } \
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andric #else
11970b57cec5SDimitry Andric // -------------------------------------------------------------------------
11980b57cec5SDimitry Andric // Code for other architectures that don't handle unaligned accesses.
11990b57cec5SDimitry Andric #define MIN_MAX_COMPXCHG(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
12000b57cec5SDimitry Andric GOMP_FLAG) \
12010b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
12020b57cec5SDimitry Andric if (*lhs OP rhs) { \
12030b57cec5SDimitry Andric GOMP_MIN_MAX_CRITSECT(OP, GOMP_FLAG) \
12040b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
12050b57cec5SDimitry Andric MIN_MAX_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
12060b57cec5SDimitry Andric } else { \
12070b57cec5SDimitry Andric KMP_CHECK_GTID; \
12080b57cec5SDimitry Andric MIN_MAX_CRITSECT(OP, LCK_ID) /* unaligned address */ \
12090b57cec5SDimitry Andric } \
12100b57cec5SDimitry Andric } \
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
12130b57cec5SDimitry Andric
12140b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed1, max, char, 8, <, 1i, 0,
12150b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_max
12160b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed1, min, char, 8, >, 1i, 0,
12170b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_min
12180b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed2, max, short, 16, <, 2i, 1,
12190b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_max
12200b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed2, min, short, 16, >, 2i, 1,
12210b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_min
12220b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed4, max, kmp_int32, 32, <, 4i, 3,
12230b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_max
12240b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed4, min, kmp_int32, 32, >, 4i, 3,
12250b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_min
12260b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed8, max, kmp_int64, 64, <, 8i, 7,
12270b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_max
12280b57cec5SDimitry Andric MIN_MAX_COMPXCHG(fixed8, min, kmp_int64, 64, >, 8i, 7,
12290b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_min
12300b57cec5SDimitry Andric MIN_MAX_COMPXCHG(float4, max, kmp_real32, 32, <, 4r, 3,
12310b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_max
12320b57cec5SDimitry Andric MIN_MAX_COMPXCHG(float4, min, kmp_real32, 32, >, 4r, 3,
12330b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_min
12340b57cec5SDimitry Andric MIN_MAX_COMPXCHG(float8, max, kmp_real64, 64, <, 8r, 7,
12350b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_max
12360b57cec5SDimitry Andric MIN_MAX_COMPXCHG(float8, min, kmp_real64, 64, >, 8r, 7,
12370b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_min
123804eeddc0SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
1239349cc55cSDimitry Andric MIN_MAX_CRITICAL(float10, max, long double, <, 10r,
1240349cc55cSDimitry Andric 1) // __kmpc_atomic_float10_max
1241349cc55cSDimitry Andric MIN_MAX_CRITICAL(float10, min, long double, >, 10r,
1242349cc55cSDimitry Andric 1) // __kmpc_atomic_float10_min
124304eeddc0SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
12440b57cec5SDimitry Andric #if KMP_HAVE_QUAD
12450b57cec5SDimitry Andric MIN_MAX_CRITICAL(float16, max, QUAD_LEGACY, <, 16r,
12460b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_max
12470b57cec5SDimitry Andric MIN_MAX_CRITICAL(float16, min, QUAD_LEGACY, >, 16r,
12480b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_min
12490b57cec5SDimitry Andric #if (KMP_ARCH_X86)
12500b57cec5SDimitry Andric MIN_MAX_CRITICAL(float16, max_a16, Quad_a16_t, <, 16r,
12510b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_max_a16
12520b57cec5SDimitry Andric MIN_MAX_CRITICAL(float16, min_a16, Quad_a16_t, >, 16r,
12530b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_min_a16
12540b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
12550b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
12560b57cec5SDimitry Andric // ------------------------------------------------------------------------
12570b57cec5SDimitry Andric // Need separate macros for .EQV. because of the need of complement (~)
12580b57cec5SDimitry Andric // OP ignored for critical sections, ^=~ used instead
12590b57cec5SDimitry Andric #define ATOMIC_CRIT_EQV(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
12600b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
1261e8d8bef9SDimitry Andric OP_GOMP_CRITICAL(^= (TYPE) ~, GOMP_FLAG) /* send assignment */ \
1262e8d8bef9SDimitry Andric OP_CRITICAL(^= (TYPE) ~, LCK_ID) /* send assignment and complement */ \
12630b57cec5SDimitry Andric }
12640b57cec5SDimitry Andric
12650b57cec5SDimitry Andric // ------------------------------------------------------------------------
12660b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
12670b57cec5SDimitry Andric // ------------------------------------------------------------------------
12680b57cec5SDimitry Andric // X86 or X86_64: no alignment problems ===================================
12690b57cec5SDimitry Andric #define ATOMIC_CMPX_EQV(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
12700b57cec5SDimitry Andric GOMP_FLAG) \
12710b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
1272e8d8bef9SDimitry Andric OP_GOMP_CRITICAL(^= (TYPE) ~, GOMP_FLAG) /* send assignment */ \
12730b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) \
12740b57cec5SDimitry Andric }
12750b57cec5SDimitry Andric // ------------------------------------------------------------------------
12760b57cec5SDimitry Andric #else
12770b57cec5SDimitry Andric // ------------------------------------------------------------------------
12780b57cec5SDimitry Andric // Code for other architectures that don't handle unaligned accesses.
12790b57cec5SDimitry Andric #define ATOMIC_CMPX_EQV(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, MASK, \
12800b57cec5SDimitry Andric GOMP_FLAG) \
12810b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
1282e8d8bef9SDimitry Andric OP_GOMP_CRITICAL(^= (TYPE) ~, GOMP_FLAG) \
12830b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
12840b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
12850b57cec5SDimitry Andric } else { \
12860b57cec5SDimitry Andric KMP_CHECK_GTID; \
1287e8d8bef9SDimitry Andric OP_CRITICAL(^= (TYPE) ~, LCK_ID) /* unaligned address - use critical */ \
12880b57cec5SDimitry Andric } \
12890b57cec5SDimitry Andric }
12900b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
12910b57cec5SDimitry Andric
12920b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed1, neqv, kmp_int8, 8, ^, 1i, 0,
12930b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_neqv
12940b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed2, neqv, kmp_int16, 16, ^, 2i, 1,
12950b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_neqv
12960b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed4, neqv, kmp_int32, 32, ^, 4i, 3,
12970b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_neqv
12980b57cec5SDimitry Andric ATOMIC_CMPXCHG(fixed8, neqv, kmp_int64, 64, ^, 8i, 7,
12990b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_neqv
13000b57cec5SDimitry Andric ATOMIC_CMPX_EQV(fixed1, eqv, kmp_int8, 8, ^~, 1i, 0,
13010b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_eqv
13020b57cec5SDimitry Andric ATOMIC_CMPX_EQV(fixed2, eqv, kmp_int16, 16, ^~, 2i, 1,
13030b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_eqv
13040b57cec5SDimitry Andric ATOMIC_CMPX_EQV(fixed4, eqv, kmp_int32, 32, ^~, 4i, 3,
13050b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_eqv
13060b57cec5SDimitry Andric ATOMIC_CMPX_EQV(fixed8, eqv, kmp_int64, 64, ^~, 8i, 7,
13070b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_eqv
13080b57cec5SDimitry Andric
13090b57cec5SDimitry Andric // ------------------------------------------------------------------------
13100b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
13110b57cec5SDimitry Andric // critical section)
13120b57cec5SDimitry Andric // TYPE_ID, OP_ID, TYPE - detailed above
13130b57cec5SDimitry Andric // OP - operator
13140b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
13150b57cec5SDimitry Andric #define ATOMIC_CRITICAL(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
13160b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
1317e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) /* send assignment */ \
1318e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, LCK_ID) /* send assignment */ \
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric
13210b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
132204eeddc0SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
13230b57cec5SDimitry Andric // routines for long double type
13240b57cec5SDimitry Andric ATOMIC_CRITICAL(float10, add, long double, +, 10r,
13250b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_add
13260b57cec5SDimitry Andric ATOMIC_CRITICAL(float10, sub, long double, -, 10r,
13270b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub
13280b57cec5SDimitry Andric ATOMIC_CRITICAL(float10, mul, long double, *, 10r,
13290b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_mul
13300b57cec5SDimitry Andric ATOMIC_CRITICAL(float10, div, long double, /, 10r,
13310b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div
133204eeddc0SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
13330b57cec5SDimitry Andric #if KMP_HAVE_QUAD
13340b57cec5SDimitry Andric // routines for _Quad type
13350b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, add, QUAD_LEGACY, +, 16r,
13360b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_add
13370b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, sub, QUAD_LEGACY, -, 16r,
13380b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub
13390b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, mul, QUAD_LEGACY, *, 16r,
13400b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_mul
13410b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, div, QUAD_LEGACY, /, 16r,
13420b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div
13430b57cec5SDimitry Andric #if (KMP_ARCH_X86)
13440b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, add_a16, Quad_a16_t, +, 16r,
13450b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_add_a16
13460b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, sub_a16, Quad_a16_t, -, 16r,
13470b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_a16
13480b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, mul_a16, Quad_a16_t, *, 16r,
13490b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_mul_a16
13500b57cec5SDimitry Andric ATOMIC_CRITICAL(float16, div_a16, Quad_a16_t, /, 16r,
13510b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_a16
13520b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
13530b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
13540b57cec5SDimitry Andric // routines for complex types
13550b57cec5SDimitry Andric
13560b57cec5SDimitry Andric #if USE_CMPXCHG_FIX
13570b57cec5SDimitry Andric // workaround for C78287 (complex(kind=4) data type)
13580b57cec5SDimitry Andric ATOMIC_CMPXCHG_WORKAROUND(cmplx4, add, kmp_cmplx32, 64, +, 8c, 7,
13590b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_add
13600b57cec5SDimitry Andric ATOMIC_CMPXCHG_WORKAROUND(cmplx4, sub, kmp_cmplx32, 64, -, 8c, 7,
13610b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_sub
13620b57cec5SDimitry Andric ATOMIC_CMPXCHG_WORKAROUND(cmplx4, mul, kmp_cmplx32, 64, *, 8c, 7,
13630b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_mul
13640b57cec5SDimitry Andric ATOMIC_CMPXCHG_WORKAROUND(cmplx4, div, kmp_cmplx32, 64, /, 8c, 7,
13650b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_div
13660b57cec5SDimitry Andric // end of the workaround for C78287
13670b57cec5SDimitry Andric #else
13680b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx4, add, kmp_cmplx32, +, 8c, 1) // __kmpc_atomic_cmplx4_add
13690b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx4, sub, kmp_cmplx32, -, 8c, 1) // __kmpc_atomic_cmplx4_sub
13700b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx4, mul, kmp_cmplx32, *, 8c, 1) // __kmpc_atomic_cmplx4_mul
13710b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx4, div, kmp_cmplx32, /, 8c, 1) // __kmpc_atomic_cmplx4_div
13720b57cec5SDimitry Andric #endif // USE_CMPXCHG_FIX
13730b57cec5SDimitry Andric
13740b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx8, add, kmp_cmplx64, +, 16c, 1) // __kmpc_atomic_cmplx8_add
13750b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx8, sub, kmp_cmplx64, -, 16c, 1) // __kmpc_atomic_cmplx8_sub
13760b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx8, mul, kmp_cmplx64, *, 16c, 1) // __kmpc_atomic_cmplx8_mul
13770b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx8, div, kmp_cmplx64, /, 16c, 1) // __kmpc_atomic_cmplx8_div
137804eeddc0SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
13790b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx10, add, kmp_cmplx80, +, 20c,
13800b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_add
13810b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx10, sub, kmp_cmplx80, -, 20c,
13820b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_sub
13830b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx10, mul, kmp_cmplx80, *, 20c,
13840b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_mul
13850b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx10, div, kmp_cmplx80, /, 20c,
13860b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_div
138704eeddc0SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
13880b57cec5SDimitry Andric #if KMP_HAVE_QUAD
13890b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, add, CPLX128_LEG, +, 32c,
13900b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_add
13910b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, sub, CPLX128_LEG, -, 32c,
13920b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub
13930b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, mul, CPLX128_LEG, *, 32c,
13940b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_mul
13950b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, div, CPLX128_LEG, /, 32c,
13960b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div
13970b57cec5SDimitry Andric #if (KMP_ARCH_X86)
13980b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, add_a16, kmp_cmplx128_a16_t, +, 32c,
13990b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_add_a16
14000b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, sub_a16, kmp_cmplx128_a16_t, -, 32c,
14010b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_a16
14020b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, mul_a16, kmp_cmplx128_a16_t, *, 32c,
14030b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_mul_a16
14040b57cec5SDimitry Andric ATOMIC_CRITICAL(cmplx16, div_a16, kmp_cmplx128_a16_t, /, 32c,
14050b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_a16
14060b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
14070b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
14080b57cec5SDimitry Andric
14090b57cec5SDimitry Andric // OpenMP 4.0: x = expr binop x for non-commutative operations.
14100b57cec5SDimitry Andric // Supported only on IA-32 architecture and Intel(R) 64
14110b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
14120b57cec5SDimitry Andric
14130b57cec5SDimitry Andric // ------------------------------------------------------------------------
14140b57cec5SDimitry Andric // Operation on *lhs, rhs bound by critical section
14150b57cec5SDimitry Andric // OP - operator (it's supposed to contain an assignment)
14160b57cec5SDimitry Andric // LCK_ID - lock identifier
14170b57cec5SDimitry Andric // Note: don't check gtid as it should always be valid
14180b57cec5SDimitry Andric // 1, 2-byte - expect valid parameter, other - check before this macro
1419e8d8bef9SDimitry Andric #define OP_CRITICAL_REV(TYPE, OP, LCK_ID) \
14200b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
14210b57cec5SDimitry Andric \
1422e8d8bef9SDimitry Andric (*lhs) = (TYPE)((rhs)OP(*lhs)); \
14230b57cec5SDimitry Andric \
14240b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
14250b57cec5SDimitry Andric
14260b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
1427e8d8bef9SDimitry Andric #define OP_GOMP_CRITICAL_REV(TYPE, OP, FLAG) \
14280b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
14290b57cec5SDimitry Andric KMP_CHECK_GTID; \
1430e8d8bef9SDimitry Andric OP_CRITICAL_REV(TYPE, OP, 0); \
14310b57cec5SDimitry Andric return; \
14320b57cec5SDimitry Andric }
1433e8d8bef9SDimitry Andric
14340b57cec5SDimitry Andric #else
1435e8d8bef9SDimitry Andric #define OP_GOMP_CRITICAL_REV(TYPE, OP, FLAG)
14360b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
14370b57cec5SDimitry Andric
14380b57cec5SDimitry Andric // Beginning of a definition (provides name, parameters, gebug trace)
14390b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned
14400b57cec5SDimitry Andric // fixed)
14410b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
14420b57cec5SDimitry Andric // TYPE - operands' type
14430b57cec5SDimitry Andric #define ATOMIC_BEGIN_REV(TYPE_ID, OP_ID, TYPE, RET_TYPE) \
14440b57cec5SDimitry Andric RET_TYPE __kmpc_atomic_##TYPE_ID##_##OP_ID##_rev(ident_t *id_ref, int gtid, \
14450b57cec5SDimitry Andric TYPE *lhs, TYPE rhs) { \
14460b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
14470b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID "_rev: T#%d\n", gtid));
14480b57cec5SDimitry Andric
14490b57cec5SDimitry Andric // ------------------------------------------------------------------------
14500b57cec5SDimitry Andric // Operation on *lhs, rhs using "compare_and_store" routine
14510b57cec5SDimitry Andric // TYPE - operands' type
14520b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
14530b57cec5SDimitry Andric // OP - operator
14540b57cec5SDimitry Andric // Note: temp_val introduced in order to force the compiler to read
14550b57cec5SDimitry Andric // *lhs only once (w/o it the compiler reads *lhs twice)
14560b57cec5SDimitry Andric #define OP_CMPXCHG_REV(TYPE, BITS, OP) \
14570b57cec5SDimitry Andric { \
14580b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
14590b57cec5SDimitry Andric TYPE old_value, new_value; \
14600b57cec5SDimitry Andric temp_val = *lhs; \
14610b57cec5SDimitry Andric old_value = temp_val; \
1462e8d8bef9SDimitry Andric new_value = (TYPE)(rhs OP old_value); \
14630b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
14640b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
14650b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & new_value)) { \
14660b57cec5SDimitry Andric KMP_DO_PAUSE; \
14670b57cec5SDimitry Andric \
14680b57cec5SDimitry Andric temp_val = *lhs; \
14690b57cec5SDimitry Andric old_value = temp_val; \
1470e8d8bef9SDimitry Andric new_value = (TYPE)(rhs OP old_value); \
14710b57cec5SDimitry Andric } \
14720b57cec5SDimitry Andric }
14730b57cec5SDimitry Andric
14740b57cec5SDimitry Andric // -------------------------------------------------------------------------
14750b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_REV(TYPE_ID, OP_ID, TYPE, BITS, OP, LCK_ID, GOMP_FLAG) \
14760b57cec5SDimitry Andric ATOMIC_BEGIN_REV(TYPE_ID, OP_ID, TYPE, void) \
1477e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_REV(TYPE, OP, GOMP_FLAG) \
14780b57cec5SDimitry Andric OP_CMPXCHG_REV(TYPE, BITS, OP) \
14790b57cec5SDimitry Andric }
14800b57cec5SDimitry Andric
14810b57cec5SDimitry Andric // ------------------------------------------------------------------------
14820b57cec5SDimitry Andric // Entries definition for integer operands
14830b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed4, float4)
14840b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
14850b57cec5SDimitry Andric // TYPE - operand type
14860b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
14870b57cec5SDimitry Andric // OP - operator (used in critical section)
14880b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
14890b57cec5SDimitry Andric
14900b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, BITS,OP,LCK_ID,GOMP_FLAG
14910b57cec5SDimitry Andric // ------------------------------------------------------------------------
14920b57cec5SDimitry Andric // Routines for ATOMIC integer operands, other operators
14930b57cec5SDimitry Andric // ------------------------------------------------------------------------
14940b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, BITS, OP, LCK_ID, GOMP_FLAG
14950b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed1, div, kmp_int8, 8, /, 1i,
14960b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_rev
14970b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed1u, div, kmp_uint8, 8, /, 1i,
14980b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_rev
14990b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed1, shl, kmp_int8, 8, <<, 1i,
15000b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shl_rev
15010b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed1, shr, kmp_int8, 8, >>, 1i,
15020b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shr_rev
15030b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed1u, shr, kmp_uint8, 8, >>, 1i,
15040b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_shr_rev
15050b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed1, sub, kmp_int8, 8, -, 1i,
15060b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_rev
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed2, div, kmp_int16, 16, /, 2i,
15090b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_rev
15100b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed2u, div, kmp_uint16, 16, /, 2i,
15110b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_rev
15120b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed2, shl, kmp_int16, 16, <<, 2i,
15130b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shl_rev
15140b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed2, shr, kmp_int16, 16, >>, 2i,
15150b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shr_rev
15160b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed2u, shr, kmp_uint16, 16, >>, 2i,
15170b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_shr_rev
15180b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed2, sub, kmp_int16, 16, -, 2i,
15190b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_rev
15200b57cec5SDimitry Andric
15210b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed4, div, kmp_int32, 32, /, 4i,
15220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_div_rev
15230b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed4u, div, kmp_uint32, 32, /, 4i,
15240b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_div_rev
15250b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed4, shl, kmp_int32, 32, <<, 4i,
15260b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shl_rev
15270b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed4, shr, kmp_int32, 32, >>, 4i,
15280b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shr_rev
15290b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed4u, shr, kmp_uint32, 32, >>, 4i,
15300b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_shr_rev
15310b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed4, sub, kmp_int32, 32, -, 4i,
15320b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_sub_rev
15330b57cec5SDimitry Andric
15340b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed8, div, kmp_int64, 64, /, 8i,
15350b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_rev
15360b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed8u, div, kmp_uint64, 64, /, 8i,
15370b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_rev
15380b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed8, shl, kmp_int64, 64, <<, 8i,
15390b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shl_rev
15400b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed8, shr, kmp_int64, 64, >>, 8i,
15410b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shr_rev
15420b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed8u, shr, kmp_uint64, 64, >>, 8i,
15430b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_shr_rev
15440b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(fixed8, sub, kmp_int64, 64, -, 8i,
15450b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_rev
15460b57cec5SDimitry Andric
15470b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(float4, div, kmp_real32, 32, /, 4r,
15480b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_rev
15490b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(float4, sub, kmp_real32, 32, -, 4r,
15500b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_rev
15510b57cec5SDimitry Andric
15520b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(float8, div, kmp_real64, 64, /, 8r,
15530b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_rev
15540b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV(float8, sub, kmp_real64, 64, -, 8r,
15550b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_rev
15560b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, BITS,OP,LCK_ID, GOMP_FLAG
15570b57cec5SDimitry Andric
15580b57cec5SDimitry Andric // ------------------------------------------------------------------------
15590b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
15600b57cec5SDimitry Andric // critical section)
15610b57cec5SDimitry Andric // TYPE_ID, OP_ID, TYPE - detailed above
15620b57cec5SDimitry Andric // OP - operator
15630b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
15640b57cec5SDimitry Andric #define ATOMIC_CRITICAL_REV(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
15650b57cec5SDimitry Andric ATOMIC_BEGIN_REV(TYPE_ID, OP_ID, TYPE, void) \
1566e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_REV(TYPE, OP, GOMP_FLAG) \
1567e8d8bef9SDimitry Andric OP_CRITICAL_REV(TYPE, OP, LCK_ID) \
15680b57cec5SDimitry Andric }
15690b57cec5SDimitry Andric
15700b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
15710b57cec5SDimitry Andric // routines for long double type
15720b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(float10, sub, long double, -, 10r,
15730b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub_rev
15740b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(float10, div, long double, /, 10r,
15750b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div_rev
15760b57cec5SDimitry Andric #if KMP_HAVE_QUAD
15770b57cec5SDimitry Andric // routines for _Quad type
15780b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(float16, sub, QUAD_LEGACY, -, 16r,
15790b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_rev
15800b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(float16, div, QUAD_LEGACY, /, 16r,
15810b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_rev
15820b57cec5SDimitry Andric #if (KMP_ARCH_X86)
15830b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(float16, sub_a16, Quad_a16_t, -, 16r,
15840b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_a16_rev
15850b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(float16, div_a16, Quad_a16_t, /, 16r,
15860b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_a16_rev
15870b57cec5SDimitry Andric #endif // KMP_ARCH_X86
15880b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
15890b57cec5SDimitry Andric
15900b57cec5SDimitry Andric // routines for complex types
15910b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx4, sub, kmp_cmplx32, -, 8c,
15920b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_sub_rev
15930b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx4, div, kmp_cmplx32, /, 8c,
15940b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_div_rev
15950b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx8, sub, kmp_cmplx64, -, 16c,
15960b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_sub_rev
15970b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx8, div, kmp_cmplx64, /, 16c,
15980b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_div_rev
15990b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx10, sub, kmp_cmplx80, -, 20c,
16000b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_sub_rev
16010b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx10, div, kmp_cmplx80, /, 20c,
16020b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_div_rev
16030b57cec5SDimitry Andric #if KMP_HAVE_QUAD
16040b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx16, sub, CPLX128_LEG, -, 32c,
16050b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_rev
16060b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx16, div, CPLX128_LEG, /, 32c,
16070b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_rev
16080b57cec5SDimitry Andric #if (KMP_ARCH_X86)
16090b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx16, sub_a16, kmp_cmplx128_a16_t, -, 32c,
16100b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_a16_rev
16110b57cec5SDimitry Andric ATOMIC_CRITICAL_REV(cmplx16, div_a16, kmp_cmplx128_a16_t, /, 32c,
16120b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_a16_rev
16130b57cec5SDimitry Andric #endif // KMP_ARCH_X86
16140b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
16150b57cec5SDimitry Andric
16160b57cec5SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
16170b57cec5SDimitry Andric // End of OpenMP 4.0: x = expr binop x for non-commutative operations.
16180b57cec5SDimitry Andric
16190b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
16200b57cec5SDimitry Andric /* Routines for mixed types of LHS and RHS, when RHS is "larger" */
16210b57cec5SDimitry Andric /* Note: in order to reduce the total number of types combinations */
16220b57cec5SDimitry Andric /* it is supposed that compiler converts RHS to longest floating type,*/
16230b57cec5SDimitry Andric /* that is _Quad, before call to any of these routines */
16240b57cec5SDimitry Andric /* Conversion to _Quad will be done by the compiler during calculation, */
16250b57cec5SDimitry Andric /* conversion back to TYPE - before the assignment, like: */
16260b57cec5SDimitry Andric /* *lhs = (TYPE)( (_Quad)(*lhs) OP rhs ) */
16270b57cec5SDimitry Andric /* Performance penalty expected because of SW emulation use */
16280b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
16290b57cec5SDimitry Andric
16300b57cec5SDimitry Andric #define ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
16310b57cec5SDimitry Andric void __kmpc_atomic_##TYPE_ID##_##OP_ID##_##RTYPE_ID( \
16320b57cec5SDimitry Andric ident_t *id_ref, int gtid, TYPE *lhs, RTYPE rhs) { \
16330b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
16340b57cec5SDimitry Andric KA_TRACE(100, \
16350b57cec5SDimitry Andric ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID "_" #RTYPE_ID ": T#%d\n", \
16360b57cec5SDimitry Andric gtid));
16370b57cec5SDimitry Andric
16380b57cec5SDimitry Andric // -------------------------------------------------------------------------
16390b57cec5SDimitry Andric #define ATOMIC_CRITICAL_FP(TYPE_ID, TYPE, OP_ID, OP, RTYPE_ID, RTYPE, LCK_ID, \
16400b57cec5SDimitry Andric GOMP_FLAG) \
16410b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1642e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) /* send assignment */ \
1643e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, LCK_ID) /* send assignment */ \
16440b57cec5SDimitry Andric }
16450b57cec5SDimitry Andric
16460b57cec5SDimitry Andric // -------------------------------------------------------------------------
16470b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
16480b57cec5SDimitry Andric // -------------------------------------------------------------------------
16490b57cec5SDimitry Andric // X86 or X86_64: no alignment problems ====================================
16500b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \
16510b57cec5SDimitry Andric LCK_ID, MASK, GOMP_FLAG) \
16520b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1653e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
16540b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) \
16550b57cec5SDimitry Andric }
16560b57cec5SDimitry Andric // -------------------------------------------------------------------------
16570b57cec5SDimitry Andric #else
16580b57cec5SDimitry Andric // ------------------------------------------------------------------------
16590b57cec5SDimitry Andric // Code for other architectures that don't handle unaligned accesses.
16600b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \
16610b57cec5SDimitry Andric LCK_ID, MASK, GOMP_FLAG) \
16620b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1663e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
16640b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
16650b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
16660b57cec5SDimitry Andric } else { \
16670b57cec5SDimitry Andric KMP_CHECK_GTID; \
1668e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, \
1669e8d8bef9SDimitry Andric LCK_ID) /* unaligned address - use critical */ \
16700b57cec5SDimitry Andric } \
16710b57cec5SDimitry Andric }
16720b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
16730b57cec5SDimitry Andric
16740b57cec5SDimitry Andric // -------------------------------------------------------------------------
16750b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
16760b57cec5SDimitry Andric // -------------------------------------------------------------------------
16770b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_REV_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, \
16780b57cec5SDimitry Andric RTYPE, LCK_ID, MASK, GOMP_FLAG) \
16790b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1680e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_REV(TYPE, OP, GOMP_FLAG) \
16810b57cec5SDimitry Andric OP_CMPXCHG_REV(TYPE, BITS, OP) \
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric #define ATOMIC_CRITICAL_REV_FP(TYPE_ID, TYPE, OP_ID, OP, RTYPE_ID, RTYPE, \
16840b57cec5SDimitry Andric LCK_ID, GOMP_FLAG) \
16850b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1686e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_REV(TYPE, OP, GOMP_FLAG) \
1687e8d8bef9SDimitry Andric OP_CRITICAL_REV(TYPE, OP, LCK_ID) \
16880b57cec5SDimitry Andric }
16890b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
16900b57cec5SDimitry Andric
16910b57cec5SDimitry Andric // RHS=float8
16920b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1, char, mul, 8, *, float8, kmp_real64, 1i, 0,
16930b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_float8
16940b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1, char, div, 8, /, float8, kmp_real64, 1i, 0,
16950b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_float8
16960b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2, short, mul, 16, *, float8, kmp_real64, 2i, 1,
16970b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_float8
16980b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2, short, div, 16, /, float8, kmp_real64, 2i, 1,
16990b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_float8
17000b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, mul, 32, *, float8, kmp_real64, 4i, 3,
17010b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_mul_float8
17020b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, div, 32, /, float8, kmp_real64, 4i, 3,
17030b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_div_float8
17040b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, mul, 64, *, float8, kmp_real64, 8i, 7,
17050b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_float8
17060b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, div, 64, /, float8, kmp_real64, 8i, 7,
17070b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_float8
17080b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, add, 32, +, float8, kmp_real64, 4r, 3,
17090b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_add_float8
17100b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, sub, 32, -, float8, kmp_real64, 4r, 3,
17110b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_float8
17120b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, mul, 32, *, float8, kmp_real64, 4r, 3,
17130b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_mul_float8
17140b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, div, 32, /, float8, kmp_real64, 4r, 3,
17150b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_float8
17160b57cec5SDimitry Andric
17170b57cec5SDimitry Andric // RHS=float16 (deprecated, to be removed when we are sure the compiler does not
17180b57cec5SDimitry Andric // use them)
17190b57cec5SDimitry Andric #if KMP_HAVE_QUAD
17200b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1, char, add, 8, +, fp, _Quad, 1i, 0,
17210b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_add_fp
17220b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1u, uchar, add, 8, +, fp, _Quad, 1i, 0,
17230b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_add_fp
17240b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1, char, sub, 8, -, fp, _Quad, 1i, 0,
17250b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_fp
17260b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1u, uchar, sub, 8, -, fp, _Quad, 1i, 0,
17270b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_fp
17280b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1, char, mul, 8, *, fp, _Quad, 1i, 0,
17290b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_fp
17300b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1u, uchar, mul, 8, *, fp, _Quad, 1i, 0,
17310b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_mul_fp
17320b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1, char, div, 8, /, fp, _Quad, 1i, 0,
17330b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_fp
17340b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed1u, uchar, div, 8, /, fp, _Quad, 1i, 0,
17350b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_fp
17360b57cec5SDimitry Andric
17370b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2, short, add, 16, +, fp, _Quad, 2i, 1,
17380b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_add_fp
17390b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2u, ushort, add, 16, +, fp, _Quad, 2i, 1,
17400b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_add_fp
17410b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2, short, sub, 16, -, fp, _Quad, 2i, 1,
17420b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_fp
17430b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2u, ushort, sub, 16, -, fp, _Quad, 2i, 1,
17440b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_fp
17450b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2, short, mul, 16, *, fp, _Quad, 2i, 1,
17460b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_fp
17470b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2u, ushort, mul, 16, *, fp, _Quad, 2i, 1,
17480b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_mul_fp
17490b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2, short, div, 16, /, fp, _Quad, 2i, 1,
17500b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_fp
17510b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed2u, ushort, div, 16, /, fp, _Quad, 2i, 1,
17520b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_fp
17530b57cec5SDimitry Andric
17540b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, add, 32, +, fp, _Quad, 4i, 3,
17550b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_add_fp
17560b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, add, 32, +, fp, _Quad, 4i, 3,
17570b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_add_fp
17580b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, sub, 32, -, fp, _Quad, 4i, 3,
17590b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_sub_fp
17600b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, sub, 32, -, fp, _Quad, 4i, 3,
17610b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_sub_fp
17620b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, mul, 32, *, fp, _Quad, 4i, 3,
17630b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_mul_fp
17640b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, mul, 32, *, fp, _Quad, 4i, 3,
17650b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_mul_fp
17660b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4, kmp_int32, div, 32, /, fp, _Quad, 4i, 3,
17670b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_div_fp
17680b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed4u, kmp_uint32, div, 32, /, fp, _Quad, 4i, 3,
17690b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_div_fp
17700b57cec5SDimitry Andric
17710b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, add, 64, +, fp, _Quad, 8i, 7,
17720b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_add_fp
17730b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, add, 64, +, fp, _Quad, 8i, 7,
17740b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_add_fp
17750b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, sub, 64, -, fp, _Quad, 8i, 7,
17760b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_fp
17770b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, sub, 64, -, fp, _Quad, 8i, 7,
17780b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_fp
17790b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, mul, 64, *, fp, _Quad, 8i, 7,
17800b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_fp
17810b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, mul, 64, *, fp, _Quad, 8i, 7,
17820b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_mul_fp
17830b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8, kmp_int64, div, 64, /, fp, _Quad, 8i, 7,
17840b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_fp
17850b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(fixed8u, kmp_uint64, div, 64, /, fp, _Quad, 8i, 7,
17860b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_fp
17870b57cec5SDimitry Andric
17880b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, add, 32, +, fp, _Quad, 4r, 3,
17890b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_add_fp
17900b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, sub, 32, -, fp, _Quad, 4r, 3,
17910b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_fp
17920b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, mul, 32, *, fp, _Quad, 4r, 3,
17930b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_mul_fp
17940b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float4, kmp_real32, div, 32, /, fp, _Quad, 4r, 3,
17950b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_fp
17960b57cec5SDimitry Andric
17970b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float8, kmp_real64, add, 64, +, fp, _Quad, 8r, 7,
17980b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_add_fp
17990b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float8, kmp_real64, sub, 64, -, fp, _Quad, 8r, 7,
18000b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_fp
18010b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float8, kmp_real64, mul, 64, *, fp, _Quad, 8r, 7,
18020b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_mul_fp
18030b57cec5SDimitry Andric ATOMIC_CMPXCHG_MIX(float8, kmp_real64, div, 64, /, fp, _Quad, 8r, 7,
18040b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_fp
18050b57cec5SDimitry Andric
180604eeddc0SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
18070b57cec5SDimitry Andric ATOMIC_CRITICAL_FP(float10, long double, add, +, fp, _Quad, 10r,
18080b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_add_fp
18090b57cec5SDimitry Andric ATOMIC_CRITICAL_FP(float10, long double, sub, -, fp, _Quad, 10r,
18100b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub_fp
18110b57cec5SDimitry Andric ATOMIC_CRITICAL_FP(float10, long double, mul, *, fp, _Quad, 10r,
18120b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_mul_fp
18130b57cec5SDimitry Andric ATOMIC_CRITICAL_FP(float10, long double, div, /, fp, _Quad, 10r,
18140b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div_fp
18150b57cec5SDimitry Andric
18160b57cec5SDimitry Andric // Reverse operations
18170b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed1, char, sub_rev, 8, -, fp, _Quad, 1i, 0,
18180b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_rev_fp
18190b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed1u, uchar, sub_rev, 8, -, fp, _Quad, 1i, 0,
18200b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_rev_fp
18210b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed1, char, div_rev, 8, /, fp, _Quad, 1i, 0,
18220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_rev_fp
18230b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed1u, uchar, div_rev, 8, /, fp, _Quad, 1i, 0,
18240b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_rev_fp
18250b57cec5SDimitry Andric
18260b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed2, short, sub_rev, 16, -, fp, _Quad, 2i, 1,
18270b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_rev_fp
18280b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed2u, ushort, sub_rev, 16, -, fp, _Quad, 2i, 1,
18290b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_rev_fp
18300b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed2, short, div_rev, 16, /, fp, _Quad, 2i, 1,
18310b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_rev_fp
18320b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed2u, ushort, div_rev, 16, /, fp, _Quad, 2i, 1,
18330b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_rev_fp
18340b57cec5SDimitry Andric
18350b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed4, kmp_int32, sub_rev, 32, -, fp, _Quad, 4i, 3,
18360b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_sub_rev_fp
18370b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed4u, kmp_uint32, sub_rev, 32, -, fp, _Quad, 4i, 3,
18380b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_sub_rev_fp
18390b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed4, kmp_int32, div_rev, 32, /, fp, _Quad, 4i, 3,
18400b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_div_rev_fp
18410b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed4u, kmp_uint32, div_rev, 32, /, fp, _Quad, 4i, 3,
18420b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_div_rev_fp
18430b57cec5SDimitry Andric
18440b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed8, kmp_int64, sub_rev, 64, -, fp, _Quad, 8i, 7,
18450b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_rev_fp
18460b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed8u, kmp_uint64, sub_rev, 64, -, fp, _Quad, 8i, 7,
18470b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_rev_fp
18480b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed8, kmp_int64, div_rev, 64, /, fp, _Quad, 8i, 7,
18490b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_rev_fp
18500b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(fixed8u, kmp_uint64, div_rev, 64, /, fp, _Quad, 8i, 7,
18510b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_rev_fp
18520b57cec5SDimitry Andric
18530b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(float4, kmp_real32, sub_rev, 32, -, fp, _Quad, 4r, 3,
18540b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_rev_fp
18550b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(float4, kmp_real32, div_rev, 32, /, fp, _Quad, 4r, 3,
18560b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_rev_fp
18570b57cec5SDimitry Andric
18580b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(float8, kmp_real64, sub_rev, 64, -, fp, _Quad, 8r, 7,
18590b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_rev_fp
18600b57cec5SDimitry Andric ATOMIC_CMPXCHG_REV_MIX(float8, kmp_real64, div_rev, 64, /, fp, _Quad, 8r, 7,
18610b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_rev_fp
18620b57cec5SDimitry Andric
18630b57cec5SDimitry Andric ATOMIC_CRITICAL_REV_FP(float10, long double, sub_rev, -, fp, _Quad, 10r,
18640b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub_rev_fp
18650b57cec5SDimitry Andric ATOMIC_CRITICAL_REV_FP(float10, long double, div_rev, /, fp, _Quad, 10r,
18660b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div_rev_fp
18670b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
18680b57cec5SDimitry Andric
18690b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
18700b57cec5SDimitry Andric
18710b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
18720b57cec5SDimitry Andric // ------------------------------------------------------------------------
18730b57cec5SDimitry Andric // X86 or X86_64: no alignment problems ====================================
18740b57cec5SDimitry Andric #if USE_CMPXCHG_FIX
18750b57cec5SDimitry Andric // workaround for C78287 (complex(kind=4) data type)
18760b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CMPLX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \
18770b57cec5SDimitry Andric LCK_ID, MASK, GOMP_FLAG) \
18780b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1879e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
18800b57cec5SDimitry Andric OP_CMPXCHG_WORKAROUND(TYPE, BITS, OP) \
18810b57cec5SDimitry Andric }
18820b57cec5SDimitry Andric // end of the second part of the workaround for C78287
18830b57cec5SDimitry Andric #else
18840b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CMPLX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \
18850b57cec5SDimitry Andric LCK_ID, MASK, GOMP_FLAG) \
18860b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1887e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
18880b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) \
18890b57cec5SDimitry Andric }
18900b57cec5SDimitry Andric #endif // USE_CMPXCHG_FIX
18910b57cec5SDimitry Andric #else
18920b57cec5SDimitry Andric // ------------------------------------------------------------------------
18930b57cec5SDimitry Andric // Code for other architectures that don't handle unaligned accesses.
18940b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CMPLX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, RTYPE, \
18950b57cec5SDimitry Andric LCK_ID, MASK, GOMP_FLAG) \
18960b57cec5SDimitry Andric ATOMIC_BEGIN_MIX(TYPE_ID, TYPE, OP_ID, RTYPE_ID, RTYPE) \
1897e8d8bef9SDimitry Andric OP_UPDATE_GOMP_CRITICAL(TYPE, OP, GOMP_FLAG) \
18980b57cec5SDimitry Andric if (!((kmp_uintptr_t)lhs & 0x##MASK)) { \
18990b57cec5SDimitry Andric OP_CMPXCHG(TYPE, BITS, OP) /* aligned address */ \
19000b57cec5SDimitry Andric } else { \
19010b57cec5SDimitry Andric KMP_CHECK_GTID; \
1902e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL(TYPE, OP, \
1903e8d8bef9SDimitry Andric LCK_ID) /* unaligned address - use critical */ \
19040b57cec5SDimitry Andric } \
19050b57cec5SDimitry Andric }
19060b57cec5SDimitry Andric #endif /* KMP_ARCH_X86 || KMP_ARCH_X86_64 */
19070b57cec5SDimitry Andric
19080b57cec5SDimitry Andric ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, add, 64, +, cmplx8, kmp_cmplx64, 8c,
19090b57cec5SDimitry Andric 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_add_cmplx8
19100b57cec5SDimitry Andric ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, sub, 64, -, cmplx8, kmp_cmplx64, 8c,
19110b57cec5SDimitry Andric 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_sub_cmplx8
19120b57cec5SDimitry Andric ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, mul, 64, *, cmplx8, kmp_cmplx64, 8c,
19130b57cec5SDimitry Andric 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_mul_cmplx8
19140b57cec5SDimitry Andric ATOMIC_CMPXCHG_CMPLX(cmplx4, kmp_cmplx32, div, 64, /, cmplx8, kmp_cmplx64, 8c,
19150b57cec5SDimitry Andric 7, KMP_ARCH_X86) // __kmpc_atomic_cmplx4_div_cmplx8
19160b57cec5SDimitry Andric
1917*bdd1243dSDimitry Andric // READ, WRITE, CAPTURE
19180b57cec5SDimitry Andric
19190b57cec5SDimitry Andric // ------------------------------------------------------------------------
19200b57cec5SDimitry Andric // Atomic READ routines
19210b57cec5SDimitry Andric
19220b57cec5SDimitry Andric // ------------------------------------------------------------------------
19230b57cec5SDimitry Andric // Beginning of a definition (provides name, parameters, gebug trace)
19240b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned
19250b57cec5SDimitry Andric // fixed)
19260b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
19270b57cec5SDimitry Andric // TYPE - operands' type
19280b57cec5SDimitry Andric #define ATOMIC_BEGIN_READ(TYPE_ID, OP_ID, TYPE, RET_TYPE) \
19290b57cec5SDimitry Andric RET_TYPE __kmpc_atomic_##TYPE_ID##_##OP_ID(ident_t *id_ref, int gtid, \
19300b57cec5SDimitry Andric TYPE *loc) { \
19310b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
19320b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID ": T#%d\n", gtid));
19330b57cec5SDimitry Andric
19340b57cec5SDimitry Andric // ------------------------------------------------------------------------
19350b57cec5SDimitry Andric // Operation on *lhs, rhs using "compare_and_store_ret" routine
19360b57cec5SDimitry Andric // TYPE - operands' type
19370b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
19380b57cec5SDimitry Andric // OP - operator
19390b57cec5SDimitry Andric // Note: temp_val introduced in order to force the compiler to read
19400b57cec5SDimitry Andric // *lhs only once (w/o it the compiler reads *lhs twice)
19410b57cec5SDimitry Andric // TODO: check if it is still necessary
19420b57cec5SDimitry Andric // Return old value regardless of the result of "compare & swap# operation
19430b57cec5SDimitry Andric #define OP_CMPXCHG_READ(TYPE, BITS, OP) \
19440b57cec5SDimitry Andric { \
19450b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
19460b57cec5SDimitry Andric union f_i_union { \
19470b57cec5SDimitry Andric TYPE f_val; \
19480b57cec5SDimitry Andric kmp_int##BITS i_val; \
19490b57cec5SDimitry Andric }; \
19500b57cec5SDimitry Andric union f_i_union old_value; \
19510b57cec5SDimitry Andric temp_val = *loc; \
19520b57cec5SDimitry Andric old_value.f_val = temp_val; \
19530b57cec5SDimitry Andric old_value.i_val = KMP_COMPARE_AND_STORE_RET##BITS( \
19540b57cec5SDimitry Andric (kmp_int##BITS *)loc, \
19550b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & old_value.i_val, \
19560b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & old_value.i_val); \
19570b57cec5SDimitry Andric new_value = old_value.f_val; \
19580b57cec5SDimitry Andric return new_value; \
19590b57cec5SDimitry Andric }
19600b57cec5SDimitry Andric
19610b57cec5SDimitry Andric // -------------------------------------------------------------------------
19620b57cec5SDimitry Andric // Operation on *lhs, rhs bound by critical section
19630b57cec5SDimitry Andric // OP - operator (it's supposed to contain an assignment)
19640b57cec5SDimitry Andric // LCK_ID - lock identifier
19650b57cec5SDimitry Andric // Note: don't check gtid as it should always be valid
19660b57cec5SDimitry Andric // 1, 2-byte - expect valid parameter, other - check before this macro
19670b57cec5SDimitry Andric #define OP_CRITICAL_READ(OP, LCK_ID) \
19680b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
19690b57cec5SDimitry Andric \
19700b57cec5SDimitry Andric new_value = (*loc); \
19710b57cec5SDimitry Andric \
19720b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
19730b57cec5SDimitry Andric
19740b57cec5SDimitry Andric // -------------------------------------------------------------------------
19750b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
19760b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_READ(OP, FLAG) \
19770b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
19780b57cec5SDimitry Andric KMP_CHECK_GTID; \
19790b57cec5SDimitry Andric OP_CRITICAL_READ(OP, 0); \
19800b57cec5SDimitry Andric return new_value; \
19810b57cec5SDimitry Andric }
19820b57cec5SDimitry Andric #else
19830b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_READ(OP, FLAG)
19840b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
19850b57cec5SDimitry Andric
19860b57cec5SDimitry Andric // -------------------------------------------------------------------------
19870b57cec5SDimitry Andric #define ATOMIC_FIXED_READ(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
19880b57cec5SDimitry Andric ATOMIC_BEGIN_READ(TYPE_ID, OP_ID, TYPE, TYPE) \
19890b57cec5SDimitry Andric TYPE new_value; \
19900b57cec5SDimitry Andric OP_GOMP_CRITICAL_READ(OP## =, GOMP_FLAG) \
19910b57cec5SDimitry Andric new_value = KMP_TEST_THEN_ADD##BITS(loc, OP 0); \
19920b57cec5SDimitry Andric return new_value; \
19930b57cec5SDimitry Andric }
19940b57cec5SDimitry Andric // -------------------------------------------------------------------------
19950b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_READ(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
19960b57cec5SDimitry Andric ATOMIC_BEGIN_READ(TYPE_ID, OP_ID, TYPE, TYPE) \
19970b57cec5SDimitry Andric TYPE new_value; \
19980b57cec5SDimitry Andric OP_GOMP_CRITICAL_READ(OP## =, GOMP_FLAG) \
19990b57cec5SDimitry Andric OP_CMPXCHG_READ(TYPE, BITS, OP) \
20000b57cec5SDimitry Andric }
20010b57cec5SDimitry Andric // ------------------------------------------------------------------------
20020b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
20030b57cec5SDimitry Andric // critical section)
20040b57cec5SDimitry Andric // TYPE_ID, OP_ID, TYPE - detailed above
20050b57cec5SDimitry Andric // OP - operator
20060b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
20070b57cec5SDimitry Andric #define ATOMIC_CRITICAL_READ(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
20080b57cec5SDimitry Andric ATOMIC_BEGIN_READ(TYPE_ID, OP_ID, TYPE, TYPE) \
20090b57cec5SDimitry Andric TYPE new_value; \
20100b57cec5SDimitry Andric OP_GOMP_CRITICAL_READ(OP## =, GOMP_FLAG) /* send assignment */ \
20110b57cec5SDimitry Andric OP_CRITICAL_READ(OP, LCK_ID) /* send assignment */ \
20120b57cec5SDimitry Andric return new_value; \
20130b57cec5SDimitry Andric }
20140b57cec5SDimitry Andric
20150b57cec5SDimitry Andric // ------------------------------------------------------------------------
20160b57cec5SDimitry Andric // Fix for cmplx4 read (CQ220361) on Windows* OS. Regular routine with return
20170b57cec5SDimitry Andric // value doesn't work.
20180b57cec5SDimitry Andric // Let's return the read value through the additional parameter.
20190b57cec5SDimitry Andric #if (KMP_OS_WINDOWS)
20200b57cec5SDimitry Andric
20210b57cec5SDimitry Andric #define OP_CRITICAL_READ_WRK(OP, LCK_ID) \
20220b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
20230b57cec5SDimitry Andric \
20240b57cec5SDimitry Andric (*out) = (*loc); \
20250b57cec5SDimitry Andric \
20260b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
20270b57cec5SDimitry Andric // ------------------------------------------------------------------------
20280b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
20290b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_READ_WRK(OP, FLAG) \
20300b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
20310b57cec5SDimitry Andric KMP_CHECK_GTID; \
20320b57cec5SDimitry Andric OP_CRITICAL_READ_WRK(OP, 0); \
20330b57cec5SDimitry Andric }
20340b57cec5SDimitry Andric #else
20350b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_READ_WRK(OP, FLAG)
20360b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
20370b57cec5SDimitry Andric // ------------------------------------------------------------------------
20380b57cec5SDimitry Andric #define ATOMIC_BEGIN_READ_WRK(TYPE_ID, OP_ID, TYPE) \
20390b57cec5SDimitry Andric void __kmpc_atomic_##TYPE_ID##_##OP_ID(TYPE *out, ident_t *id_ref, int gtid, \
20400b57cec5SDimitry Andric TYPE *loc) { \
20410b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
20420b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID ": T#%d\n", gtid));
20430b57cec5SDimitry Andric
20440b57cec5SDimitry Andric // ------------------------------------------------------------------------
20450b57cec5SDimitry Andric #define ATOMIC_CRITICAL_READ_WRK(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
20460b57cec5SDimitry Andric ATOMIC_BEGIN_READ_WRK(TYPE_ID, OP_ID, TYPE) \
20470b57cec5SDimitry Andric OP_GOMP_CRITICAL_READ_WRK(OP## =, GOMP_FLAG) /* send assignment */ \
20480b57cec5SDimitry Andric OP_CRITICAL_READ_WRK(OP, LCK_ID) /* send assignment */ \
20490b57cec5SDimitry Andric }
20500b57cec5SDimitry Andric
20510b57cec5SDimitry Andric #endif // KMP_OS_WINDOWS
20520b57cec5SDimitry Andric
20530b57cec5SDimitry Andric // ------------------------------------------------------------------------
20540b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG
20550b57cec5SDimitry Andric ATOMIC_FIXED_READ(fixed4, rd, kmp_int32, 32, +, 0) // __kmpc_atomic_fixed4_rd
20560b57cec5SDimitry Andric ATOMIC_FIXED_READ(fixed8, rd, kmp_int64, 64, +,
20570b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_rd
20580b57cec5SDimitry Andric ATOMIC_CMPXCHG_READ(float4, rd, kmp_real32, 32, +,
20590b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_rd
20600b57cec5SDimitry Andric ATOMIC_CMPXCHG_READ(float8, rd, kmp_real64, 64, +,
20610b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_rd
20620b57cec5SDimitry Andric
20630b57cec5SDimitry Andric // !!! TODO: Remove lock operations for "char" since it can't be non-atomic
20640b57cec5SDimitry Andric ATOMIC_CMPXCHG_READ(fixed1, rd, kmp_int8, 8, +,
20650b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_rd
20660b57cec5SDimitry Andric ATOMIC_CMPXCHG_READ(fixed2, rd, kmp_int16, 16, +,
20670b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_rd
20680b57cec5SDimitry Andric
20690b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(float10, rd, long double, +, 10r,
20700b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_rd
20710b57cec5SDimitry Andric #if KMP_HAVE_QUAD
20720b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(float16, rd, QUAD_LEGACY, +, 16r,
20730b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_rd
20740b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
20750b57cec5SDimitry Andric
20760b57cec5SDimitry Andric // Fix for CQ220361 on Windows* OS
20770b57cec5SDimitry Andric #if (KMP_OS_WINDOWS)
20780b57cec5SDimitry Andric ATOMIC_CRITICAL_READ_WRK(cmplx4, rd, kmp_cmplx32, +, 8c,
20790b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_rd
20800b57cec5SDimitry Andric #else
20810b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(cmplx4, rd, kmp_cmplx32, +, 8c,
20820b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_rd
20830b57cec5SDimitry Andric #endif // (KMP_OS_WINDOWS)
20840b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(cmplx8, rd, kmp_cmplx64, +, 16c,
20850b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_rd
20860b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(cmplx10, rd, kmp_cmplx80, +, 20c,
20870b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_rd
20880b57cec5SDimitry Andric #if KMP_HAVE_QUAD
20890b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(cmplx16, rd, CPLX128_LEG, +, 32c,
20900b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_rd
20910b57cec5SDimitry Andric #if (KMP_ARCH_X86)
20920b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(float16, a16_rd, Quad_a16_t, +, 16r,
20930b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_a16_rd
20940b57cec5SDimitry Andric ATOMIC_CRITICAL_READ(cmplx16, a16_rd, kmp_cmplx128_a16_t, +, 32c,
20950b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_a16_rd
20960b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
20970b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
20980b57cec5SDimitry Andric
20990b57cec5SDimitry Andric // ------------------------------------------------------------------------
21000b57cec5SDimitry Andric // Atomic WRITE routines
21010b57cec5SDimitry Andric
21020b57cec5SDimitry Andric #define ATOMIC_XCHG_WR(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
21030b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
21040b57cec5SDimitry Andric OP_GOMP_CRITICAL(OP, GOMP_FLAG) \
21050b57cec5SDimitry Andric KMP_XCHG_FIXED##BITS(lhs, rhs); \
21060b57cec5SDimitry Andric }
21070b57cec5SDimitry Andric // ------------------------------------------------------------------------
21080b57cec5SDimitry Andric #define ATOMIC_XCHG_FLOAT_WR(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
21090b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
21100b57cec5SDimitry Andric OP_GOMP_CRITICAL(OP, GOMP_FLAG) \
21110b57cec5SDimitry Andric KMP_XCHG_REAL##BITS(lhs, rhs); \
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric
21140b57cec5SDimitry Andric // ------------------------------------------------------------------------
21150b57cec5SDimitry Andric // Operation on *lhs, rhs using "compare_and_store" routine
21160b57cec5SDimitry Andric // TYPE - operands' type
21170b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
21180b57cec5SDimitry Andric // OP - operator
21190b57cec5SDimitry Andric // Note: temp_val introduced in order to force the compiler to read
21200b57cec5SDimitry Andric // *lhs only once (w/o it the compiler reads *lhs twice)
21210b57cec5SDimitry Andric #define OP_CMPXCHG_WR(TYPE, BITS, OP) \
21220b57cec5SDimitry Andric { \
21230b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
21240b57cec5SDimitry Andric TYPE old_value, new_value; \
21250b57cec5SDimitry Andric temp_val = *lhs; \
21260b57cec5SDimitry Andric old_value = temp_val; \
21270b57cec5SDimitry Andric new_value = rhs; \
21280b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
21290b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
21300b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & new_value)) { \
21310b57cec5SDimitry Andric temp_val = *lhs; \
21320b57cec5SDimitry Andric old_value = temp_val; \
21330b57cec5SDimitry Andric new_value = rhs; \
21340b57cec5SDimitry Andric } \
21350b57cec5SDimitry Andric }
21360b57cec5SDimitry Andric
21370b57cec5SDimitry Andric // -------------------------------------------------------------------------
21380b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_WR(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
21390b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
21400b57cec5SDimitry Andric OP_GOMP_CRITICAL(OP, GOMP_FLAG) \
21410b57cec5SDimitry Andric OP_CMPXCHG_WR(TYPE, BITS, OP) \
21420b57cec5SDimitry Andric }
21430b57cec5SDimitry Andric
21440b57cec5SDimitry Andric // ------------------------------------------------------------------------
21450b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
21460b57cec5SDimitry Andric // critical section)
21470b57cec5SDimitry Andric // TYPE_ID, OP_ID, TYPE - detailed above
21480b57cec5SDimitry Andric // OP - operator
21490b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
21500b57cec5SDimitry Andric #define ATOMIC_CRITICAL_WR(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
21510b57cec5SDimitry Andric ATOMIC_BEGIN(TYPE_ID, OP_ID, TYPE, void) \
21520b57cec5SDimitry Andric OP_GOMP_CRITICAL(OP, GOMP_FLAG) /* send assignment */ \
21530b57cec5SDimitry Andric OP_CRITICAL(OP, LCK_ID) /* send assignment */ \
21540b57cec5SDimitry Andric }
21550b57cec5SDimitry Andric // -------------------------------------------------------------------------
21560b57cec5SDimitry Andric
21570b57cec5SDimitry Andric ATOMIC_XCHG_WR(fixed1, wr, kmp_int8, 8, =,
21580b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_wr
21590b57cec5SDimitry Andric ATOMIC_XCHG_WR(fixed2, wr, kmp_int16, 16, =,
21600b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_wr
21610b57cec5SDimitry Andric ATOMIC_XCHG_WR(fixed4, wr, kmp_int32, 32, =,
21620b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_wr
21630b57cec5SDimitry Andric #if (KMP_ARCH_X86)
21640b57cec5SDimitry Andric ATOMIC_CMPXCHG_WR(fixed8, wr, kmp_int64, 64, =,
21650b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_wr
21660b57cec5SDimitry Andric #else
21670b57cec5SDimitry Andric ATOMIC_XCHG_WR(fixed8, wr, kmp_int64, 64, =,
21680b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_wr
21690b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
21700b57cec5SDimitry Andric
21710b57cec5SDimitry Andric ATOMIC_XCHG_FLOAT_WR(float4, wr, kmp_real32, 32, =,
21720b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_wr
21730b57cec5SDimitry Andric #if (KMP_ARCH_X86)
21740b57cec5SDimitry Andric ATOMIC_CMPXCHG_WR(float8, wr, kmp_real64, 64, =,
21750b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_wr
21760b57cec5SDimitry Andric #else
21770b57cec5SDimitry Andric ATOMIC_XCHG_FLOAT_WR(float8, wr, kmp_real64, 64, =,
21780b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_wr
21790b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
21800b57cec5SDimitry Andric
21810b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(float10, wr, long double, =, 10r,
21820b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_wr
21830b57cec5SDimitry Andric #if KMP_HAVE_QUAD
21840b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(float16, wr, QUAD_LEGACY, =, 16r,
21850b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_wr
21860b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
21870b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(cmplx4, wr, kmp_cmplx32, =, 8c, 1) // __kmpc_atomic_cmplx4_wr
21880b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(cmplx8, wr, kmp_cmplx64, =, 16c,
21890b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_wr
21900b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(cmplx10, wr, kmp_cmplx80, =, 20c,
21910b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_wr
21920b57cec5SDimitry Andric #if KMP_HAVE_QUAD
21930b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(cmplx16, wr, CPLX128_LEG, =, 32c,
21940b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_wr
21950b57cec5SDimitry Andric #if (KMP_ARCH_X86)
21960b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(float16, a16_wr, Quad_a16_t, =, 16r,
21970b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_a16_wr
21980b57cec5SDimitry Andric ATOMIC_CRITICAL_WR(cmplx16, a16_wr, kmp_cmplx128_a16_t, =, 32c,
21990b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_a16_wr
22000b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
22010b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
22020b57cec5SDimitry Andric
22030b57cec5SDimitry Andric // ------------------------------------------------------------------------
22040b57cec5SDimitry Andric // Atomic CAPTURE routines
22050b57cec5SDimitry Andric
22060b57cec5SDimitry Andric // Beginning of a definition (provides name, parameters, gebug trace)
22070b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned
22080b57cec5SDimitry Andric // fixed)
22090b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
22100b57cec5SDimitry Andric // TYPE - operands' type
22110b57cec5SDimitry Andric #define ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, RET_TYPE) \
22120b57cec5SDimitry Andric RET_TYPE __kmpc_atomic_##TYPE_ID##_##OP_ID(ident_t *id_ref, int gtid, \
22130b57cec5SDimitry Andric TYPE *lhs, TYPE rhs, int flag) { \
22140b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
22150b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID ": T#%d\n", gtid));
22160b57cec5SDimitry Andric
22170b57cec5SDimitry Andric // -------------------------------------------------------------------------
22180b57cec5SDimitry Andric // Operation on *lhs, rhs bound by critical section
22190b57cec5SDimitry Andric // OP - operator (it's supposed to contain an assignment)
22200b57cec5SDimitry Andric // LCK_ID - lock identifier
22210b57cec5SDimitry Andric // Note: don't check gtid as it should always be valid
22220b57cec5SDimitry Andric // 1, 2-byte - expect valid parameter, other - check before this macro
22230b57cec5SDimitry Andric #define OP_CRITICAL_CPT(OP, LCK_ID) \
22240b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
22250b57cec5SDimitry Andric \
22260b57cec5SDimitry Andric if (flag) { \
22270b57cec5SDimitry Andric (*lhs) OP rhs; \
22280b57cec5SDimitry Andric new_value = (*lhs); \
22290b57cec5SDimitry Andric } else { \
22300b57cec5SDimitry Andric new_value = (*lhs); \
22310b57cec5SDimitry Andric (*lhs) OP rhs; \
22320b57cec5SDimitry Andric } \
22330b57cec5SDimitry Andric \
22340b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
22350b57cec5SDimitry Andric return new_value;
22360b57cec5SDimitry Andric
2237e8d8bef9SDimitry Andric #define OP_UPDATE_CRITICAL_CPT(TYPE, OP, LCK_ID) \
2238e8d8bef9SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
2239e8d8bef9SDimitry Andric \
2240e8d8bef9SDimitry Andric if (flag) { \
2241e8d8bef9SDimitry Andric (*lhs) = (TYPE)((*lhs)OP rhs); \
2242e8d8bef9SDimitry Andric new_value = (*lhs); \
2243e8d8bef9SDimitry Andric } else { \
2244e8d8bef9SDimitry Andric new_value = (*lhs); \
2245e8d8bef9SDimitry Andric (*lhs) = (TYPE)((*lhs)OP rhs); \
2246e8d8bef9SDimitry Andric } \
2247e8d8bef9SDimitry Andric \
2248e8d8bef9SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
2249e8d8bef9SDimitry Andric return new_value;
2250e8d8bef9SDimitry Andric
22510b57cec5SDimitry Andric // ------------------------------------------------------------------------
22520b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
2253e8d8bef9SDimitry Andric #define OP_GOMP_CRITICAL_CPT(TYPE, OP, FLAG) \
22540b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
22550b57cec5SDimitry Andric KMP_CHECK_GTID; \
2256e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL_CPT(TYPE, OP, 0); \
22570b57cec5SDimitry Andric }
22580b57cec5SDimitry Andric #else
2259e8d8bef9SDimitry Andric #define OP_GOMP_CRITICAL_CPT(TYPE, OP, FLAG)
22600b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
22610b57cec5SDimitry Andric
22620b57cec5SDimitry Andric // ------------------------------------------------------------------------
22630b57cec5SDimitry Andric // Operation on *lhs, rhs using "compare_and_store" routine
22640b57cec5SDimitry Andric // TYPE - operands' type
22650b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
22660b57cec5SDimitry Andric // OP - operator
22670b57cec5SDimitry Andric // Note: temp_val introduced in order to force the compiler to read
22680b57cec5SDimitry Andric // *lhs only once (w/o it the compiler reads *lhs twice)
22690b57cec5SDimitry Andric #define OP_CMPXCHG_CPT(TYPE, BITS, OP) \
22700b57cec5SDimitry Andric { \
22710b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
22720b57cec5SDimitry Andric TYPE old_value, new_value; \
22730b57cec5SDimitry Andric temp_val = *lhs; \
22740b57cec5SDimitry Andric old_value = temp_val; \
2275e8d8bef9SDimitry Andric new_value = (TYPE)(old_value OP rhs); \
22760b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
22770b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
22780b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & new_value)) { \
22790b57cec5SDimitry Andric temp_val = *lhs; \
22800b57cec5SDimitry Andric old_value = temp_val; \
2281e8d8bef9SDimitry Andric new_value = (TYPE)(old_value OP rhs); \
22820b57cec5SDimitry Andric } \
22830b57cec5SDimitry Andric if (flag) { \
22840b57cec5SDimitry Andric return new_value; \
22850b57cec5SDimitry Andric } else \
22860b57cec5SDimitry Andric return old_value; \
22870b57cec5SDimitry Andric }
22880b57cec5SDimitry Andric
22890b57cec5SDimitry Andric // -------------------------------------------------------------------------
22900b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
22910b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
22920b57cec5SDimitry Andric TYPE new_value; \
2293fe6060f1SDimitry Andric (void)new_value; \
2294e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT(TYPE, OP, GOMP_FLAG) \
22950b57cec5SDimitry Andric OP_CMPXCHG_CPT(TYPE, BITS, OP) \
22960b57cec5SDimitry Andric }
22970b57cec5SDimitry Andric
22980b57cec5SDimitry Andric // -------------------------------------------------------------------------
22990b57cec5SDimitry Andric #define ATOMIC_FIXED_ADD_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
23000b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
23010b57cec5SDimitry Andric TYPE old_value, new_value; \
2302fe6060f1SDimitry Andric (void)new_value; \
2303e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT(TYPE, OP, GOMP_FLAG) \
23040b57cec5SDimitry Andric /* OP used as a sign for subtraction: (lhs-rhs) --> (lhs+-rhs) */ \
23050b57cec5SDimitry Andric old_value = KMP_TEST_THEN_ADD##BITS(lhs, OP rhs); \
23060b57cec5SDimitry Andric if (flag) { \
23070b57cec5SDimitry Andric return old_value OP rhs; \
23080b57cec5SDimitry Andric } else \
23090b57cec5SDimitry Andric return old_value; \
23100b57cec5SDimitry Andric }
23110b57cec5SDimitry Andric // -------------------------------------------------------------------------
23120b57cec5SDimitry Andric
23130b57cec5SDimitry Andric ATOMIC_FIXED_ADD_CPT(fixed4, add_cpt, kmp_int32, 32, +,
23140b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_add_cpt
23150b57cec5SDimitry Andric ATOMIC_FIXED_ADD_CPT(fixed4, sub_cpt, kmp_int32, 32, -,
23160b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_sub_cpt
23170b57cec5SDimitry Andric ATOMIC_FIXED_ADD_CPT(fixed8, add_cpt, kmp_int64, 64, +,
23180b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_add_cpt
23190b57cec5SDimitry Andric ATOMIC_FIXED_ADD_CPT(fixed8, sub_cpt, kmp_int64, 64, -,
23200b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_cpt
23210b57cec5SDimitry Andric
23220b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float4, add_cpt, kmp_real32, 32, +,
23230b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_add_cpt
23240b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float4, sub_cpt, kmp_real32, 32, -,
23250b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_cpt
23260b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float8, add_cpt, kmp_real64, 64, +,
23270b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_add_cpt
23280b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float8, sub_cpt, kmp_real64, 64, -,
23290b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_cpt
23300b57cec5SDimitry Andric
23310b57cec5SDimitry Andric // ------------------------------------------------------------------------
23320b57cec5SDimitry Andric // Entries definition for integer operands
23330b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed4, float4)
23340b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
23350b57cec5SDimitry Andric // TYPE - operand type
23360b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
23370b57cec5SDimitry Andric // OP - operator (used in critical section)
23380b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, BITS,OP,GOMP_FLAG
23390b57cec5SDimitry Andric // ------------------------------------------------------------------------
23400b57cec5SDimitry Andric // Routines for ATOMIC integer operands, other operators
23410b57cec5SDimitry Andric // ------------------------------------------------------------------------
23420b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG
23430b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, add_cpt, kmp_int8, 8, +,
23440b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_add_cpt
23450b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, andb_cpt, kmp_int8, 8, &,
23460b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed1_andb_cpt
23470b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, div_cpt, kmp_int8, 8, /,
23480b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_cpt
23490b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1u, div_cpt, kmp_uint8, 8, /,
23500b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_cpt
23510b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, mul_cpt, kmp_int8, 8, *,
23520b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_cpt
23530b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, orb_cpt, kmp_int8, 8, |,
23540b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed1_orb_cpt
23550b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, shl_cpt, kmp_int8, 8, <<,
23560b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shl_cpt
23570b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, shr_cpt, kmp_int8, 8, >>,
23580b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shr_cpt
23590b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1u, shr_cpt, kmp_uint8, 8, >>,
23600b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_shr_cpt
23610b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, sub_cpt, kmp_int8, 8, -,
23620b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_cpt
23630b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, xor_cpt, kmp_int8, 8, ^,
23640b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed1_xor_cpt
23650b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, add_cpt, kmp_int16, 16, +,
23660b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_add_cpt
23670b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, andb_cpt, kmp_int16, 16, &,
23680b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed2_andb_cpt
23690b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, div_cpt, kmp_int16, 16, /,
23700b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_cpt
23710b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2u, div_cpt, kmp_uint16, 16, /,
23720b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_cpt
23730b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, mul_cpt, kmp_int16, 16, *,
23740b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_cpt
23750b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, orb_cpt, kmp_int16, 16, |,
23760b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed2_orb_cpt
23770b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, shl_cpt, kmp_int16, 16, <<,
23780b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shl_cpt
23790b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, shr_cpt, kmp_int16, 16, >>,
23800b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shr_cpt
23810b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2u, shr_cpt, kmp_uint16, 16, >>,
23820b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_shr_cpt
23830b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, sub_cpt, kmp_int16, 16, -,
23840b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_cpt
23850b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, xor_cpt, kmp_int16, 16, ^,
23860b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed2_xor_cpt
23870b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, andb_cpt, kmp_int32, 32, &,
23880b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_andb_cpt
23890b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, div_cpt, kmp_int32, 32, /,
23900b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_div_cpt
23910b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4u, div_cpt, kmp_uint32, 32, /,
23920b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_div_cpt
23930b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, mul_cpt, kmp_int32, 32, *,
23940b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_mul_cpt
23950b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, orb_cpt, kmp_int32, 32, |,
23960b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_orb_cpt
23970b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, shl_cpt, kmp_int32, 32, <<,
23980b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shl_cpt
23990b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, shr_cpt, kmp_int32, 32, >>,
24000b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shr_cpt
24010b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4u, shr_cpt, kmp_uint32, 32, >>,
24020b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_shr_cpt
24030b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, xor_cpt, kmp_int32, 32, ^,
24040b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_xor_cpt
24050b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, andb_cpt, kmp_int64, 64, &,
24060b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_andb_cpt
24070b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, div_cpt, kmp_int64, 64, /,
24080b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_cpt
24090b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8u, div_cpt, kmp_uint64, 64, /,
24100b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_cpt
24110b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, mul_cpt, kmp_int64, 64, *,
24120b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_cpt
24130b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, orb_cpt, kmp_int64, 64, |,
24140b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_orb_cpt
24150b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, shl_cpt, kmp_int64, 64, <<,
24160b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shl_cpt
24170b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, shr_cpt, kmp_int64, 64, >>,
24180b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shr_cpt
24190b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8u, shr_cpt, kmp_uint64, 64, >>,
24200b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_shr_cpt
24210b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, xor_cpt, kmp_int64, 64, ^,
24220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_xor_cpt
24230b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float4, div_cpt, kmp_real32, 32, /,
24240b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_cpt
24250b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float4, mul_cpt, kmp_real32, 32, *,
24260b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_mul_cpt
24270b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float8, div_cpt, kmp_real64, 64, /,
24280b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_cpt
24290b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(float8, mul_cpt, kmp_real64, 64, *,
24300b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_mul_cpt
24310b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG
24320b57cec5SDimitry Andric
24330b57cec5SDimitry Andric // CAPTURE routines for mixed types RHS=float16
24340b57cec5SDimitry Andric #if KMP_HAVE_QUAD
24350b57cec5SDimitry Andric
24360b57cec5SDimitry Andric // Beginning of a definition (provides name, parameters, gebug trace)
24370b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned
24380b57cec5SDimitry Andric // fixed)
24390b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
24400b57cec5SDimitry Andric // TYPE - operands' type
24410b57cec5SDimitry Andric #define ATOMIC_BEGIN_CPT_MIX(TYPE_ID, OP_ID, TYPE, RTYPE_ID, RTYPE) \
24420b57cec5SDimitry Andric TYPE __kmpc_atomic_##TYPE_ID##_##OP_ID##_##RTYPE_ID( \
24430b57cec5SDimitry Andric ident_t *id_ref, int gtid, TYPE *lhs, RTYPE rhs, int flag) { \
24440b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
24450b57cec5SDimitry Andric KA_TRACE(100, \
24460b57cec5SDimitry Andric ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID "_" #RTYPE_ID ": T#%d\n", \
24470b57cec5SDimitry Andric gtid));
24480b57cec5SDimitry Andric
24490b57cec5SDimitry Andric // -------------------------------------------------------------------------
24500b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CPT_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, \
24510b57cec5SDimitry Andric RTYPE, LCK_ID, MASK, GOMP_FLAG) \
24520b57cec5SDimitry Andric ATOMIC_BEGIN_CPT_MIX(TYPE_ID, OP_ID, TYPE, RTYPE_ID, RTYPE) \
24530b57cec5SDimitry Andric TYPE new_value; \
245481ad6265SDimitry Andric (void)new_value; \
2455e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT(TYPE, OP, GOMP_FLAG) \
24560b57cec5SDimitry Andric OP_CMPXCHG_CPT(TYPE, BITS, OP) \
24570b57cec5SDimitry Andric }
24580b57cec5SDimitry Andric
24590b57cec5SDimitry Andric // -------------------------------------------------------------------------
24600b57cec5SDimitry Andric #define ATOMIC_CRITICAL_CPT_MIX(TYPE_ID, TYPE, OP_ID, OP, RTYPE_ID, RTYPE, \
24610b57cec5SDimitry Andric LCK_ID, GOMP_FLAG) \
24620b57cec5SDimitry Andric ATOMIC_BEGIN_CPT_MIX(TYPE_ID, OP_ID, TYPE, RTYPE_ID, RTYPE) \
24630b57cec5SDimitry Andric TYPE new_value; \
246481ad6265SDimitry Andric (void)new_value; \
2465e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT(TYPE, OP, GOMP_FLAG) /* send assignment */ \
2466e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL_CPT(TYPE, OP, LCK_ID) /* send assignment */ \
24670b57cec5SDimitry Andric }
24680b57cec5SDimitry Andric
24690b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, add_cpt, 8, +, fp, _Quad, 1i, 0,
24700b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_add_cpt_fp
24710b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, add_cpt, 8, +, fp, _Quad, 1i, 0,
24720b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_add_cpt_fp
24730b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, sub_cpt, 8, -, fp, _Quad, 1i, 0,
24740b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_cpt_fp
24750b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, sub_cpt, 8, -, fp, _Quad, 1i, 0,
24760b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_cpt_fp
24770b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, mul_cpt, 8, *, fp, _Quad, 1i, 0,
24780b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_mul_cpt_fp
24790b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, mul_cpt, 8, *, fp, _Quad, 1i, 0,
24800b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_mul_cpt_fp
24810b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1, char, div_cpt, 8, /, fp, _Quad, 1i, 0,
24820b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_cpt_fp
24830b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed1u, uchar, div_cpt, 8, /, fp, _Quad, 1i, 0,
24840b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_cpt_fp
24850b57cec5SDimitry Andric
24860b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, add_cpt, 16, +, fp, _Quad, 2i, 1,
24870b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_add_cpt_fp
24880b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, add_cpt, 16, +, fp, _Quad, 2i, 1,
24890b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_add_cpt_fp
24900b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, sub_cpt, 16, -, fp, _Quad, 2i, 1,
24910b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_cpt_fp
24920b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, sub_cpt, 16, -, fp, _Quad, 2i, 1,
24930b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_cpt_fp
24940b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, mul_cpt, 16, *, fp, _Quad, 2i, 1,
24950b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_mul_cpt_fp
24960b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, mul_cpt, 16, *, fp, _Quad, 2i, 1,
24970b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_mul_cpt_fp
24980b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2, short, div_cpt, 16, /, fp, _Quad, 2i, 1,
24990b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_cpt_fp
25000b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed2u, ushort, div_cpt, 16, /, fp, _Quad, 2i, 1,
25010b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_cpt_fp
25020b57cec5SDimitry Andric
25030b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, add_cpt, 32, +, fp, _Quad, 4i, 3,
25040b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_add_cpt_fp
25050b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, add_cpt, 32, +, fp, _Quad, 4i, 3,
25060b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_add_cpt_fp
25070b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, sub_cpt, 32, -, fp, _Quad, 4i, 3,
25080b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_sub_cpt_fp
25090b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, sub_cpt, 32, -, fp, _Quad, 4i, 3,
25100b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_sub_cpt_fp
25110b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, mul_cpt, 32, *, fp, _Quad, 4i, 3,
25120b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_mul_cpt_fp
25130b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, mul_cpt, 32, *, fp, _Quad, 4i, 3,
25140b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_mul_cpt_fp
25150b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4, kmp_int32, div_cpt, 32, /, fp, _Quad, 4i, 3,
25160b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_div_cpt_fp
25170b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed4u, kmp_uint32, div_cpt, 32, /, fp, _Quad, 4i, 3,
25180b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4u_div_cpt_fp
25190b57cec5SDimitry Andric
25200b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, add_cpt, 64, +, fp, _Quad, 8i, 7,
25210b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_add_cpt_fp
25220b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, add_cpt, 64, +, fp, _Quad, 8i, 7,
25230b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_add_cpt_fp
25240b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, sub_cpt, 64, -, fp, _Quad, 8i, 7,
25250b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_cpt_fp
25260b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, sub_cpt, 64, -, fp, _Quad, 8i, 7,
25270b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_cpt_fp
25280b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, mul_cpt, 64, *, fp, _Quad, 8i, 7,
25290b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_mul_cpt_fp
25300b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, mul_cpt, 64, *, fp, _Quad, 8i, 7,
25310b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_mul_cpt_fp
25320b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8, kmp_int64, div_cpt, 64, /, fp, _Quad, 8i, 7,
25330b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_cpt_fp
25340b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(fixed8u, kmp_uint64, div_cpt, 64, /, fp, _Quad, 8i, 7,
25350b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_cpt_fp
25360b57cec5SDimitry Andric
25370b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, add_cpt, 32, +, fp, _Quad, 4r, 3,
25380b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_add_cpt_fp
25390b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, sub_cpt, 32, -, fp, _Quad, 4r, 3,
25400b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_cpt_fp
25410b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, mul_cpt, 32, *, fp, _Quad, 4r, 3,
25420b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_mul_cpt_fp
25430b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float4, kmp_real32, div_cpt, 32, /, fp, _Quad, 4r, 3,
25440b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_cpt_fp
25450b57cec5SDimitry Andric
25460b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, add_cpt, 64, +, fp, _Quad, 8r, 7,
25470b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_add_cpt_fp
25480b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, sub_cpt, 64, -, fp, _Quad, 8r, 7,
25490b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_cpt_fp
25500b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, mul_cpt, 64, *, fp, _Quad, 8r, 7,
25510b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_mul_cpt_fp
25520b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_MIX(float8, kmp_real64, div_cpt, 64, /, fp, _Quad, 8r, 7,
25530b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_cpt_fp
25540b57cec5SDimitry Andric
25550b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_MIX(float10, long double, add_cpt, +, fp, _Quad, 10r,
25560b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_add_cpt_fp
25570b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_MIX(float10, long double, sub_cpt, -, fp, _Quad, 10r,
25580b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub_cpt_fp
25590b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_MIX(float10, long double, mul_cpt, *, fp, _Quad, 10r,
25600b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_mul_cpt_fp
25610b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_MIX(float10, long double, div_cpt, /, fp, _Quad, 10r,
25620b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div_cpt_fp
25630b57cec5SDimitry Andric
25640b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
25650b57cec5SDimitry Andric
25660b57cec5SDimitry Andric // ------------------------------------------------------------------------
25670b57cec5SDimitry Andric // Routines for C/C++ Reduction operators && and ||
25680b57cec5SDimitry Andric
25690b57cec5SDimitry Andric // -------------------------------------------------------------------------
25700b57cec5SDimitry Andric // Operation on *lhs, rhs bound by critical section
25710b57cec5SDimitry Andric // OP - operator (it's supposed to contain an assignment)
25720b57cec5SDimitry Andric // LCK_ID - lock identifier
25730b57cec5SDimitry Andric // Note: don't check gtid as it should always be valid
25740b57cec5SDimitry Andric // 1, 2-byte - expect valid parameter, other - check before this macro
25750b57cec5SDimitry Andric #define OP_CRITICAL_L_CPT(OP, LCK_ID) \
25760b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
25770b57cec5SDimitry Andric \
25780b57cec5SDimitry Andric if (flag) { \
25790b57cec5SDimitry Andric new_value OP rhs; \
2580e8d8bef9SDimitry Andric (*lhs) = new_value; \
2581e8d8bef9SDimitry Andric } else { \
25820b57cec5SDimitry Andric new_value = (*lhs); \
2583e8d8bef9SDimitry Andric (*lhs) OP rhs; \
2584e8d8bef9SDimitry Andric } \
25850b57cec5SDimitry Andric \
25860b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid);
25870b57cec5SDimitry Andric
25880b57cec5SDimitry Andric // ------------------------------------------------------------------------
25890b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
25900b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_L_CPT(OP, FLAG) \
25910b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
25920b57cec5SDimitry Andric KMP_CHECK_GTID; \
25930b57cec5SDimitry Andric OP_CRITICAL_L_CPT(OP, 0); \
25940b57cec5SDimitry Andric return new_value; \
25950b57cec5SDimitry Andric }
25960b57cec5SDimitry Andric #else
25970b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_L_CPT(OP, FLAG)
25980b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
25990b57cec5SDimitry Andric
26000b57cec5SDimitry Andric // ------------------------------------------------------------------------
26010b57cec5SDimitry Andric // Need separate macros for &&, || because there is no combined assignment
26020b57cec5SDimitry Andric #define ATOMIC_CMPX_L_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
26030b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
26040b57cec5SDimitry Andric TYPE new_value; \
2605fe6060f1SDimitry Andric (void)new_value; \
26060b57cec5SDimitry Andric OP_GOMP_CRITICAL_L_CPT(= *lhs OP, GOMP_FLAG) \
26070b57cec5SDimitry Andric OP_CMPXCHG_CPT(TYPE, BITS, OP) \
26080b57cec5SDimitry Andric }
26090b57cec5SDimitry Andric
26100b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed1, andl_cpt, char, 8, &&,
26110b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_andl_cpt
26120b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed1, orl_cpt, char, 8, ||,
26130b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_orl_cpt
26140b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed2, andl_cpt, short, 16, &&,
26150b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_andl_cpt
26160b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed2, orl_cpt, short, 16, ||,
26170b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_orl_cpt
26180b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed4, andl_cpt, kmp_int32, 32, &&,
26190b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_andl_cpt
26200b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed4, orl_cpt, kmp_int32, 32, ||,
26210b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_orl_cpt
26220b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed8, andl_cpt, kmp_int64, 64, &&,
26230b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_andl_cpt
26240b57cec5SDimitry Andric ATOMIC_CMPX_L_CPT(fixed8, orl_cpt, kmp_int64, 64, ||,
26250b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_orl_cpt
26260b57cec5SDimitry Andric
26270b57cec5SDimitry Andric // -------------------------------------------------------------------------
26280b57cec5SDimitry Andric // Routines for Fortran operators that matched no one in C:
26290b57cec5SDimitry Andric // MAX, MIN, .EQV., .NEQV.
26300b57cec5SDimitry Andric // Operators .AND., .OR. are covered by __kmpc_atomic_*_{andl,orl}_cpt
26310b57cec5SDimitry Andric // Intrinsics IAND, IOR, IEOR are covered by __kmpc_atomic_*_{andb,orb,xor}_cpt
26320b57cec5SDimitry Andric
26330b57cec5SDimitry Andric // -------------------------------------------------------------------------
26340b57cec5SDimitry Andric // MIN and MAX need separate macros
26350b57cec5SDimitry Andric // OP - operator to check if we need any actions?
26360b57cec5SDimitry Andric #define MIN_MAX_CRITSECT_CPT(OP, LCK_ID) \
26370b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
26380b57cec5SDimitry Andric \
26390b57cec5SDimitry Andric if (*lhs OP rhs) { /* still need actions? */ \
26400b57cec5SDimitry Andric old_value = *lhs; \
26410b57cec5SDimitry Andric *lhs = rhs; \
26420b57cec5SDimitry Andric if (flag) \
26430b57cec5SDimitry Andric new_value = rhs; \
26440b57cec5SDimitry Andric else \
26450b57cec5SDimitry Andric new_value = old_value; \
26460b57cec5SDimitry Andric } else { \
26470b57cec5SDimitry Andric new_value = *lhs; \
26480b57cec5SDimitry Andric } \
26490b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
26500b57cec5SDimitry Andric return new_value;
26510b57cec5SDimitry Andric
26520b57cec5SDimitry Andric // -------------------------------------------------------------------------
26530b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
26540b57cec5SDimitry Andric #define GOMP_MIN_MAX_CRITSECT_CPT(OP, FLAG) \
26550b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
26560b57cec5SDimitry Andric KMP_CHECK_GTID; \
26570b57cec5SDimitry Andric MIN_MAX_CRITSECT_CPT(OP, 0); \
26580b57cec5SDimitry Andric }
26590b57cec5SDimitry Andric #else
26600b57cec5SDimitry Andric #define GOMP_MIN_MAX_CRITSECT_CPT(OP, FLAG)
26610b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
26620b57cec5SDimitry Andric
26630b57cec5SDimitry Andric // -------------------------------------------------------------------------
26640b57cec5SDimitry Andric #define MIN_MAX_CMPXCHG_CPT(TYPE, BITS, OP) \
26650b57cec5SDimitry Andric { \
26660b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
26670b57cec5SDimitry Andric /*TYPE old_value; */ \
26680b57cec5SDimitry Andric temp_val = *lhs; \
26690b57cec5SDimitry Andric old_value = temp_val; \
26700b57cec5SDimitry Andric while (old_value OP rhs && /* still need actions? */ \
26710b57cec5SDimitry Andric !KMP_COMPARE_AND_STORE_ACQ##BITS( \
26720b57cec5SDimitry Andric (kmp_int##BITS *)lhs, \
26730b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
26740b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & rhs)) { \
26750b57cec5SDimitry Andric temp_val = *lhs; \
26760b57cec5SDimitry Andric old_value = temp_val; \
26770b57cec5SDimitry Andric } \
26780b57cec5SDimitry Andric if (flag) \
26790b57cec5SDimitry Andric return rhs; \
26800b57cec5SDimitry Andric else \
26810b57cec5SDimitry Andric return old_value; \
26820b57cec5SDimitry Andric }
26830b57cec5SDimitry Andric
26840b57cec5SDimitry Andric // -------------------------------------------------------------------------
26850b57cec5SDimitry Andric // 1-byte, 2-byte operands - use critical section
26860b57cec5SDimitry Andric #define MIN_MAX_CRITICAL_CPT(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
26870b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
26880b57cec5SDimitry Andric TYPE new_value, old_value; \
26890b57cec5SDimitry Andric if (*lhs OP rhs) { /* need actions? */ \
26900b57cec5SDimitry Andric GOMP_MIN_MAX_CRITSECT_CPT(OP, GOMP_FLAG) \
26910b57cec5SDimitry Andric MIN_MAX_CRITSECT_CPT(OP, LCK_ID) \
26920b57cec5SDimitry Andric } \
26930b57cec5SDimitry Andric return *lhs; \
26940b57cec5SDimitry Andric }
26950b57cec5SDimitry Andric
26960b57cec5SDimitry Andric #define MIN_MAX_COMPXCHG_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
26970b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
26980b57cec5SDimitry Andric TYPE new_value, old_value; \
2699fe6060f1SDimitry Andric (void)new_value; \
27000b57cec5SDimitry Andric if (*lhs OP rhs) { \
27010b57cec5SDimitry Andric GOMP_MIN_MAX_CRITSECT_CPT(OP, GOMP_FLAG) \
27020b57cec5SDimitry Andric MIN_MAX_CMPXCHG_CPT(TYPE, BITS, OP) \
27030b57cec5SDimitry Andric } \
27040b57cec5SDimitry Andric return *lhs; \
27050b57cec5SDimitry Andric }
27060b57cec5SDimitry Andric
27070b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed1, max_cpt, char, 8, <,
27080b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_max_cpt
27090b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed1, min_cpt, char, 8, >,
27100b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_min_cpt
27110b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed2, max_cpt, short, 16, <,
27120b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_max_cpt
27130b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed2, min_cpt, short, 16, >,
27140b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_min_cpt
27150b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed4, max_cpt, kmp_int32, 32, <,
27160b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_max_cpt
27170b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed4, min_cpt, kmp_int32, 32, >,
27180b57cec5SDimitry Andric 0) // __kmpc_atomic_fixed4_min_cpt
27190b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed8, max_cpt, kmp_int64, 64, <,
27200b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_max_cpt
27210b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(fixed8, min_cpt, kmp_int64, 64, >,
27220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_min_cpt
27230b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(float4, max_cpt, kmp_real32, 32, <,
27240b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_max_cpt
27250b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(float4, min_cpt, kmp_real32, 32, >,
27260b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_min_cpt
27270b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(float8, max_cpt, kmp_real64, 64, <,
27280b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_max_cpt
27290b57cec5SDimitry Andric MIN_MAX_COMPXCHG_CPT(float8, min_cpt, kmp_real64, 64, >,
27300b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_min_cpt
2731349cc55cSDimitry Andric MIN_MAX_CRITICAL_CPT(float10, max_cpt, long double, <, 10r,
2732349cc55cSDimitry Andric 1) // __kmpc_atomic_float10_max_cpt
2733349cc55cSDimitry Andric MIN_MAX_CRITICAL_CPT(float10, min_cpt, long double, >, 10r,
2734349cc55cSDimitry Andric 1) // __kmpc_atomic_float10_min_cpt
27350b57cec5SDimitry Andric #if KMP_HAVE_QUAD
27360b57cec5SDimitry Andric MIN_MAX_CRITICAL_CPT(float16, max_cpt, QUAD_LEGACY, <, 16r,
27370b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_max_cpt
27380b57cec5SDimitry Andric MIN_MAX_CRITICAL_CPT(float16, min_cpt, QUAD_LEGACY, >, 16r,
27390b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_min_cpt
27400b57cec5SDimitry Andric #if (KMP_ARCH_X86)
27410b57cec5SDimitry Andric MIN_MAX_CRITICAL_CPT(float16, max_a16_cpt, Quad_a16_t, <, 16r,
27420b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_max_a16_cpt
27430b57cec5SDimitry Andric MIN_MAX_CRITICAL_CPT(float16, min_a16_cpt, Quad_a16_t, >, 16r,
27440b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_mix_a16_cpt
27450b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
27460b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
27470b57cec5SDimitry Andric
27480b57cec5SDimitry Andric // ------------------------------------------------------------------------
27490b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
27500b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_EQV_CPT(OP, FLAG) \
27510b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
27520b57cec5SDimitry Andric KMP_CHECK_GTID; \
27530b57cec5SDimitry Andric OP_CRITICAL_CPT(OP, 0); \
27540b57cec5SDimitry Andric }
27550b57cec5SDimitry Andric #else
27560b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_EQV_CPT(OP, FLAG)
27570b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
27580b57cec5SDimitry Andric // ------------------------------------------------------------------------
27590b57cec5SDimitry Andric #define ATOMIC_CMPX_EQV_CPT(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
27600b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
27610b57cec5SDimitry Andric TYPE new_value; \
2762fe6060f1SDimitry Andric (void)new_value; \
2763e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_EQV_CPT(^= (TYPE) ~, GOMP_FLAG) /* send assignment */ \
27640b57cec5SDimitry Andric OP_CMPXCHG_CPT(TYPE, BITS, OP) \
27650b57cec5SDimitry Andric }
27660b57cec5SDimitry Andric
27670b57cec5SDimitry Andric // ------------------------------------------------------------------------
27680b57cec5SDimitry Andric
27690b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed1, neqv_cpt, kmp_int8, 8, ^,
27700b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_neqv_cpt
27710b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed2, neqv_cpt, kmp_int16, 16, ^,
27720b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_neqv_cpt
27730b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed4, neqv_cpt, kmp_int32, 32, ^,
27740b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_neqv_cpt
27750b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT(fixed8, neqv_cpt, kmp_int64, 64, ^,
27760b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_neqv_cpt
27770b57cec5SDimitry Andric ATOMIC_CMPX_EQV_CPT(fixed1, eqv_cpt, kmp_int8, 8, ^~,
27780b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_eqv_cpt
27790b57cec5SDimitry Andric ATOMIC_CMPX_EQV_CPT(fixed2, eqv_cpt, kmp_int16, 16, ^~,
27800b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_eqv_cpt
27810b57cec5SDimitry Andric ATOMIC_CMPX_EQV_CPT(fixed4, eqv_cpt, kmp_int32, 32, ^~,
27820b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_eqv_cpt
27830b57cec5SDimitry Andric ATOMIC_CMPX_EQV_CPT(fixed8, eqv_cpt, kmp_int64, 64, ^~,
27840b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_eqv_cpt
27850b57cec5SDimitry Andric
27860b57cec5SDimitry Andric // ------------------------------------------------------------------------
27870b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
27880b57cec5SDimitry Andric // critical section)
27890b57cec5SDimitry Andric // TYPE_ID, OP_ID, TYPE - detailed above
27900b57cec5SDimitry Andric // OP - operator
27910b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
27920b57cec5SDimitry Andric #define ATOMIC_CRITICAL_CPT(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
27930b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
27940b57cec5SDimitry Andric TYPE new_value; \
2795e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT(TYPE, OP, GOMP_FLAG) /* send assignment */ \
2796e8d8bef9SDimitry Andric OP_UPDATE_CRITICAL_CPT(TYPE, OP, LCK_ID) /* send assignment */ \
27970b57cec5SDimitry Andric }
27980b57cec5SDimitry Andric
27990b57cec5SDimitry Andric // ------------------------------------------------------------------------
28000b57cec5SDimitry Andric // Workaround for cmplx4. Regular routines with return value don't work
28010b57cec5SDimitry Andric // on Win_32e. Let's return captured values through the additional parameter.
28020b57cec5SDimitry Andric #define OP_CRITICAL_CPT_WRK(OP, LCK_ID) \
28030b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
28040b57cec5SDimitry Andric \
28050b57cec5SDimitry Andric if (flag) { \
28060b57cec5SDimitry Andric (*lhs) OP rhs; \
28070b57cec5SDimitry Andric (*out) = (*lhs); \
28080b57cec5SDimitry Andric } else { \
28090b57cec5SDimitry Andric (*out) = (*lhs); \
28100b57cec5SDimitry Andric (*lhs) OP rhs; \
28110b57cec5SDimitry Andric } \
28120b57cec5SDimitry Andric \
28130b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
28140b57cec5SDimitry Andric return;
28150b57cec5SDimitry Andric // ------------------------------------------------------------------------
28160b57cec5SDimitry Andric
28170b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
28180b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_CPT_WRK(OP, FLAG) \
28190b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
28200b57cec5SDimitry Andric KMP_CHECK_GTID; \
28210b57cec5SDimitry Andric OP_CRITICAL_CPT_WRK(OP## =, 0); \
28220b57cec5SDimitry Andric }
28230b57cec5SDimitry Andric #else
28240b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_CPT_WRK(OP, FLAG)
28250b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
28260b57cec5SDimitry Andric // ------------------------------------------------------------------------
28270b57cec5SDimitry Andric
28280b57cec5SDimitry Andric #define ATOMIC_BEGIN_WRK(TYPE_ID, OP_ID, TYPE) \
28290b57cec5SDimitry Andric void __kmpc_atomic_##TYPE_ID##_##OP_ID(ident_t *id_ref, int gtid, TYPE *lhs, \
28300b57cec5SDimitry Andric TYPE rhs, TYPE *out, int flag) { \
28310b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
28320b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_" #OP_ID ": T#%d\n", gtid));
28330b57cec5SDimitry Andric // ------------------------------------------------------------------------
28340b57cec5SDimitry Andric
28350b57cec5SDimitry Andric #define ATOMIC_CRITICAL_CPT_WRK(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
28360b57cec5SDimitry Andric ATOMIC_BEGIN_WRK(TYPE_ID, OP_ID, TYPE) \
28370b57cec5SDimitry Andric OP_GOMP_CRITICAL_CPT_WRK(OP, GOMP_FLAG) \
28380b57cec5SDimitry Andric OP_CRITICAL_CPT_WRK(OP## =, LCK_ID) \
28390b57cec5SDimitry Andric }
28400b57cec5SDimitry Andric // The end of workaround for cmplx4
28410b57cec5SDimitry Andric
28420b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
28430b57cec5SDimitry Andric // routines for long double type
28440b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float10, add_cpt, long double, +, 10r,
28450b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_add_cpt
28460b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float10, sub_cpt, long double, -, 10r,
28470b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub_cpt
28480b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float10, mul_cpt, long double, *, 10r,
28490b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_mul_cpt
28500b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float10, div_cpt, long double, /, 10r,
28510b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div_cpt
28520b57cec5SDimitry Andric #if KMP_HAVE_QUAD
28530b57cec5SDimitry Andric // routines for _Quad type
28540b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, add_cpt, QUAD_LEGACY, +, 16r,
28550b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_add_cpt
28560b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, sub_cpt, QUAD_LEGACY, -, 16r,
28570b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_cpt
28580b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, mul_cpt, QUAD_LEGACY, *, 16r,
28590b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_mul_cpt
28600b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, div_cpt, QUAD_LEGACY, /, 16r,
28610b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_cpt
28620b57cec5SDimitry Andric #if (KMP_ARCH_X86)
28630b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, add_a16_cpt, Quad_a16_t, +, 16r,
28640b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_add_a16_cpt
28650b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, sub_a16_cpt, Quad_a16_t, -, 16r,
28660b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_a16_cpt
28670b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, mul_a16_cpt, Quad_a16_t, *, 16r,
28680b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_mul_a16_cpt
28690b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(float16, div_a16_cpt, Quad_a16_t, /, 16r,
28700b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_a16_cpt
28710b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
28720b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
28730b57cec5SDimitry Andric
28740b57cec5SDimitry Andric // routines for complex types
28750b57cec5SDimitry Andric
28760b57cec5SDimitry Andric // cmplx4 routines to return void
28770b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_WRK(cmplx4, add_cpt, kmp_cmplx32, +, 8c,
28780b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_add_cpt
28790b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_WRK(cmplx4, sub_cpt, kmp_cmplx32, -, 8c,
28800b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_sub_cpt
28810b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_WRK(cmplx4, mul_cpt, kmp_cmplx32, *, 8c,
28820b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_mul_cpt
28830b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_WRK(cmplx4, div_cpt, kmp_cmplx32, /, 8c,
28840b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_div_cpt
28850b57cec5SDimitry Andric
28860b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx8, add_cpt, kmp_cmplx64, +, 16c,
28870b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_add_cpt
28880b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx8, sub_cpt, kmp_cmplx64, -, 16c,
28890b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_sub_cpt
28900b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx8, mul_cpt, kmp_cmplx64, *, 16c,
28910b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_mul_cpt
28920b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx8, div_cpt, kmp_cmplx64, /, 16c,
28930b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_div_cpt
28940b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx10, add_cpt, kmp_cmplx80, +, 20c,
28950b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_add_cpt
28960b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx10, sub_cpt, kmp_cmplx80, -, 20c,
28970b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_sub_cpt
28980b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx10, mul_cpt, kmp_cmplx80, *, 20c,
28990b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_mul_cpt
29000b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx10, div_cpt, kmp_cmplx80, /, 20c,
29010b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_div_cpt
29020b57cec5SDimitry Andric #if KMP_HAVE_QUAD
29030b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, add_cpt, CPLX128_LEG, +, 32c,
29040b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_add_cpt
29050b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, sub_cpt, CPLX128_LEG, -, 32c,
29060b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_cpt
29070b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, mul_cpt, CPLX128_LEG, *, 32c,
29080b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_mul_cpt
29090b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, div_cpt, CPLX128_LEG, /, 32c,
29100b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_cpt
29110b57cec5SDimitry Andric #if (KMP_ARCH_X86)
29120b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, add_a16_cpt, kmp_cmplx128_a16_t, +, 32c,
29130b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_add_a16_cpt
29140b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, sub_a16_cpt, kmp_cmplx128_a16_t, -, 32c,
29150b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_a16_cpt
29160b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, mul_a16_cpt, kmp_cmplx128_a16_t, *, 32c,
29170b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_mul_a16_cpt
29180b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT(cmplx16, div_a16_cpt, kmp_cmplx128_a16_t, /, 32c,
29190b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_a16_cpt
29200b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
29210b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
29220b57cec5SDimitry Andric
29230b57cec5SDimitry Andric // OpenMP 4.0: v = x = expr binop x; { v = x; x = expr binop x; } { x = expr
29240b57cec5SDimitry Andric // binop x; v = x; } for non-commutative operations.
29250b57cec5SDimitry Andric // Supported only on IA-32 architecture and Intel(R) 64
29260b57cec5SDimitry Andric
2927*bdd1243dSDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
29280b57cec5SDimitry Andric // -------------------------------------------------------------------------
29290b57cec5SDimitry Andric // Operation on *lhs, rhs bound by critical section
29300b57cec5SDimitry Andric // OP - operator (it's supposed to contain an assignment)
29310b57cec5SDimitry Andric // LCK_ID - lock identifier
29320b57cec5SDimitry Andric // Note: don't check gtid as it should always be valid
29330b57cec5SDimitry Andric // 1, 2-byte - expect valid parameter, other - check before this macro
2934e8d8bef9SDimitry Andric #define OP_CRITICAL_CPT_REV(TYPE, OP, LCK_ID) \
29350b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
29360b57cec5SDimitry Andric \
29370b57cec5SDimitry Andric if (flag) { \
29380b57cec5SDimitry Andric /*temp_val = (*lhs);*/ \
2939e8d8bef9SDimitry Andric (*lhs) = (TYPE)((rhs)OP(*lhs)); \
29400b57cec5SDimitry Andric new_value = (*lhs); \
29410b57cec5SDimitry Andric } else { \
29420b57cec5SDimitry Andric new_value = (*lhs); \
2943e8d8bef9SDimitry Andric (*lhs) = (TYPE)((rhs)OP(*lhs)); \
29440b57cec5SDimitry Andric } \
29450b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
29460b57cec5SDimitry Andric return new_value;
29470b57cec5SDimitry Andric
29480b57cec5SDimitry Andric // ------------------------------------------------------------------------
29490b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
2950e8d8bef9SDimitry Andric #define OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, FLAG) \
29510b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
29520b57cec5SDimitry Andric KMP_CHECK_GTID; \
2953e8d8bef9SDimitry Andric OP_CRITICAL_CPT_REV(TYPE, OP, 0); \
29540b57cec5SDimitry Andric }
29550b57cec5SDimitry Andric #else
2956e8d8bef9SDimitry Andric #define OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, FLAG)
29570b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
29580b57cec5SDimitry Andric
29590b57cec5SDimitry Andric // ------------------------------------------------------------------------
29600b57cec5SDimitry Andric // Operation on *lhs, rhs using "compare_and_store" routine
29610b57cec5SDimitry Andric // TYPE - operands' type
29620b57cec5SDimitry Andric // BITS - size in bits, used to distinguish low level calls
29630b57cec5SDimitry Andric // OP - operator
29640b57cec5SDimitry Andric // Note: temp_val introduced in order to force the compiler to read
29650b57cec5SDimitry Andric // *lhs only once (w/o it the compiler reads *lhs twice)
29660b57cec5SDimitry Andric #define OP_CMPXCHG_CPT_REV(TYPE, BITS, OP) \
29670b57cec5SDimitry Andric { \
29680b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
29690b57cec5SDimitry Andric TYPE old_value, new_value; \
29700b57cec5SDimitry Andric temp_val = *lhs; \
29710b57cec5SDimitry Andric old_value = temp_val; \
2972e8d8bef9SDimitry Andric new_value = (TYPE)(rhs OP old_value); \
29730b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
29740b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
29750b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & new_value)) { \
29760b57cec5SDimitry Andric temp_val = *lhs; \
29770b57cec5SDimitry Andric old_value = temp_val; \
2978e8d8bef9SDimitry Andric new_value = (TYPE)(rhs OP old_value); \
29790b57cec5SDimitry Andric } \
29800b57cec5SDimitry Andric if (flag) { \
29810b57cec5SDimitry Andric return new_value; \
29820b57cec5SDimitry Andric } else \
29830b57cec5SDimitry Andric return old_value; \
29840b57cec5SDimitry Andric }
29850b57cec5SDimitry Andric
29860b57cec5SDimitry Andric // -------------------------------------------------------------------------
29870b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CPT_REV(TYPE_ID, OP_ID, TYPE, BITS, OP, GOMP_FLAG) \
29880b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
29890b57cec5SDimitry Andric TYPE new_value; \
2990fe6060f1SDimitry Andric (void)new_value; \
2991e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, GOMP_FLAG) \
29920b57cec5SDimitry Andric OP_CMPXCHG_CPT_REV(TYPE, BITS, OP) \
29930b57cec5SDimitry Andric }
29940b57cec5SDimitry Andric
29950b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed1, div_cpt_rev, kmp_int8, 8, /,
29960b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_cpt_rev
29970b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed1u, div_cpt_rev, kmp_uint8, 8, /,
29980b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_cpt_rev
29990b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed1, shl_cpt_rev, kmp_int8, 8, <<,
30000b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shl_cpt_rev
30010b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed1, shr_cpt_rev, kmp_int8, 8, >>,
30020b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_shr_cpt_rev
30030b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed1u, shr_cpt_rev, kmp_uint8, 8, >>,
30040b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_shr_cpt_rev
30050b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed1, sub_cpt_rev, kmp_int8, 8, -,
30060b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_cpt_rev
30070b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed2, div_cpt_rev, kmp_int16, 16, /,
30080b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_cpt_rev
30090b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed2u, div_cpt_rev, kmp_uint16, 16, /,
30100b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_cpt_rev
30110b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed2, shl_cpt_rev, kmp_int16, 16, <<,
30120b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shl_cpt_rev
30130b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed2, shr_cpt_rev, kmp_int16, 16, >>,
30140b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_shr_cpt_rev
30150b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed2u, shr_cpt_rev, kmp_uint16, 16, >>,
30160b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_shr_cpt_rev
30170b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed2, sub_cpt_rev, kmp_int16, 16, -,
30180b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_cpt_rev
30190b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed4, div_cpt_rev, kmp_int32, 32, /,
30200b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_div_cpt_rev
30210b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed4u, div_cpt_rev, kmp_uint32, 32, /,
30220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_div_cpt_rev
30230b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed4, shl_cpt_rev, kmp_int32, 32, <<,
30240b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shl_cpt_rev
30250b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed4, shr_cpt_rev, kmp_int32, 32, >>,
30260b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_shr_cpt_rev
30270b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed4u, shr_cpt_rev, kmp_uint32, 32, >>,
30280b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4u_shr_cpt_rev
30290b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed4, sub_cpt_rev, kmp_int32, 32, -,
30300b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed4_sub_cpt_rev
30310b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed8, div_cpt_rev, kmp_int64, 64, /,
30320b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_cpt_rev
30330b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed8u, div_cpt_rev, kmp_uint64, 64, /,
30340b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_cpt_rev
30350b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed8, shl_cpt_rev, kmp_int64, 64, <<,
30360b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shl_cpt_rev
30370b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed8, shr_cpt_rev, kmp_int64, 64, >>,
30380b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_shr_cpt_rev
30390b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed8u, shr_cpt_rev, kmp_uint64, 64, >>,
30400b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_shr_cpt_rev
30410b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(fixed8, sub_cpt_rev, kmp_int64, 64, -,
30420b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_cpt_rev
30430b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(float4, div_cpt_rev, kmp_real32, 32, /,
30440b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_cpt_rev
30450b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(float4, sub_cpt_rev, kmp_real32, 32, -,
30460b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_cpt_rev
30470b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(float8, div_cpt_rev, kmp_real64, 64, /,
30480b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_cpt_rev
30490b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV(float8, sub_cpt_rev, kmp_real64, 64, -,
30500b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_cpt_rev
30510b57cec5SDimitry Andric // TYPE_ID,OP_ID, TYPE, OP, GOMP_FLAG
30520b57cec5SDimitry Andric
30530b57cec5SDimitry Andric // ------------------------------------------------------------------------
30540b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
30550b57cec5SDimitry Andric // critical section)
30560b57cec5SDimitry Andric // TYPE_ID, OP_ID, TYPE - detailed above
30570b57cec5SDimitry Andric // OP - operator
30580b57cec5SDimitry Andric // LCK_ID - lock identifier, used to possibly distinguish lock variable
30590b57cec5SDimitry Andric #define ATOMIC_CRITICAL_CPT_REV(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, GOMP_FLAG) \
30600b57cec5SDimitry Andric ATOMIC_BEGIN_CPT(TYPE_ID, OP_ID, TYPE, TYPE) \
30610b57cec5SDimitry Andric TYPE new_value; \
30620b57cec5SDimitry Andric /*printf("__kmp_atomic_mode = %d\n", __kmp_atomic_mode);*/ \
3063e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, GOMP_FLAG) \
3064e8d8bef9SDimitry Andric OP_CRITICAL_CPT_REV(TYPE, OP, LCK_ID) \
30650b57cec5SDimitry Andric }
30660b57cec5SDimitry Andric
30670b57cec5SDimitry Andric /* ------------------------------------------------------------------------- */
30680b57cec5SDimitry Andric // routines for long double type
30690b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(float10, sub_cpt_rev, long double, -, 10r,
30700b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_sub_cpt_rev
30710b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(float10, div_cpt_rev, long double, /, 10r,
30720b57cec5SDimitry Andric 1) // __kmpc_atomic_float10_div_cpt_rev
30730b57cec5SDimitry Andric #if KMP_HAVE_QUAD
30740b57cec5SDimitry Andric // routines for _Quad type
30750b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(float16, sub_cpt_rev, QUAD_LEGACY, -, 16r,
30760b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_cpt_rev
30770b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(float16, div_cpt_rev, QUAD_LEGACY, /, 16r,
30780b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_cpt_rev
30790b57cec5SDimitry Andric #if (KMP_ARCH_X86)
30800b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(float16, sub_a16_cpt_rev, Quad_a16_t, -, 16r,
30810b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_sub_a16_cpt_rev
30820b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(float16, div_a16_cpt_rev, Quad_a16_t, /, 16r,
30830b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_div_a16_cpt_rev
30840b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
30850b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
30860b57cec5SDimitry Andric
30870b57cec5SDimitry Andric // routines for complex types
30880b57cec5SDimitry Andric
30890b57cec5SDimitry Andric // ------------------------------------------------------------------------
30900b57cec5SDimitry Andric // Workaround for cmplx4. Regular routines with return value don't work
30910b57cec5SDimitry Andric // on Win_32e. Let's return captured values through the additional parameter.
30920b57cec5SDimitry Andric #define OP_CRITICAL_CPT_REV_WRK(OP, LCK_ID) \
30930b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
30940b57cec5SDimitry Andric \
30950b57cec5SDimitry Andric if (flag) { \
30960b57cec5SDimitry Andric (*lhs) = (rhs)OP(*lhs); \
30970b57cec5SDimitry Andric (*out) = (*lhs); \
30980b57cec5SDimitry Andric } else { \
30990b57cec5SDimitry Andric (*out) = (*lhs); \
31000b57cec5SDimitry Andric (*lhs) = (rhs)OP(*lhs); \
31010b57cec5SDimitry Andric } \
31020b57cec5SDimitry Andric \
31030b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
31040b57cec5SDimitry Andric return;
31050b57cec5SDimitry Andric // ------------------------------------------------------------------------
31060b57cec5SDimitry Andric
31070b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
31080b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_CPT_REV_WRK(OP, FLAG) \
31090b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
31100b57cec5SDimitry Andric KMP_CHECK_GTID; \
31110b57cec5SDimitry Andric OP_CRITICAL_CPT_REV_WRK(OP, 0); \
31120b57cec5SDimitry Andric }
31130b57cec5SDimitry Andric #else
31140b57cec5SDimitry Andric #define OP_GOMP_CRITICAL_CPT_REV_WRK(OP, FLAG)
31150b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
31160b57cec5SDimitry Andric // ------------------------------------------------------------------------
31170b57cec5SDimitry Andric
31180b57cec5SDimitry Andric #define ATOMIC_CRITICAL_CPT_REV_WRK(TYPE_ID, OP_ID, TYPE, OP, LCK_ID, \
31190b57cec5SDimitry Andric GOMP_FLAG) \
31200b57cec5SDimitry Andric ATOMIC_BEGIN_WRK(TYPE_ID, OP_ID, TYPE) \
31210b57cec5SDimitry Andric OP_GOMP_CRITICAL_CPT_REV_WRK(OP, GOMP_FLAG) \
31220b57cec5SDimitry Andric OP_CRITICAL_CPT_REV_WRK(OP, LCK_ID) \
31230b57cec5SDimitry Andric }
31240b57cec5SDimitry Andric // The end of workaround for cmplx4
31250b57cec5SDimitry Andric
31260b57cec5SDimitry Andric // !!! TODO: check if we need to return void for cmplx4 routines
31270b57cec5SDimitry Andric // cmplx4 routines to return void
31280b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV_WRK(cmplx4, sub_cpt_rev, kmp_cmplx32, -, 8c,
31290b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_sub_cpt_rev
31300b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV_WRK(cmplx4, div_cpt_rev, kmp_cmplx32, /, 8c,
31310b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx4_div_cpt_rev
31320b57cec5SDimitry Andric
31330b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx8, sub_cpt_rev, kmp_cmplx64, -, 16c,
31340b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_sub_cpt_rev
31350b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx8, div_cpt_rev, kmp_cmplx64, /, 16c,
31360b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx8_div_cpt_rev
31370b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx10, sub_cpt_rev, kmp_cmplx80, -, 20c,
31380b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_sub_cpt_rev
31390b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx10, div_cpt_rev, kmp_cmplx80, /, 20c,
31400b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx10_div_cpt_rev
31410b57cec5SDimitry Andric #if KMP_HAVE_QUAD
31420b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx16, sub_cpt_rev, CPLX128_LEG, -, 32c,
31430b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_cpt_rev
31440b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx16, div_cpt_rev, CPLX128_LEG, /, 32c,
31450b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_cpt_rev
31460b57cec5SDimitry Andric #if (KMP_ARCH_X86)
31470b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx16, sub_a16_cpt_rev, kmp_cmplx128_a16_t, -, 32c,
31480b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_sub_a16_cpt_rev
31490b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV(cmplx16, div_a16_cpt_rev, kmp_cmplx128_a16_t, /, 32c,
31500b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_div_a16_cpt_rev
31510b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
31520b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
31530b57cec5SDimitry Andric
31540b57cec5SDimitry Andric // Capture reverse for mixed type: RHS=float16
31550b57cec5SDimitry Andric #if KMP_HAVE_QUAD
31560b57cec5SDimitry Andric
31570b57cec5SDimitry Andric // Beginning of a definition (provides name, parameters, gebug trace)
31580b57cec5SDimitry Andric // TYPE_ID - operands type and size (fixed*, fixed*u for signed, unsigned
31590b57cec5SDimitry Andric // fixed)
31600b57cec5SDimitry Andric // OP_ID - operation identifier (add, sub, mul, ...)
31610b57cec5SDimitry Andric // TYPE - operands' type
31620b57cec5SDimitry Andric // -------------------------------------------------------------------------
31630b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_CPT_REV_MIX(TYPE_ID, TYPE, OP_ID, BITS, OP, RTYPE_ID, \
31640b57cec5SDimitry Andric RTYPE, LCK_ID, MASK, GOMP_FLAG) \
31650b57cec5SDimitry Andric ATOMIC_BEGIN_CPT_MIX(TYPE_ID, OP_ID, TYPE, RTYPE_ID, RTYPE) \
31660b57cec5SDimitry Andric TYPE new_value; \
316781ad6265SDimitry Andric (void)new_value; \
3168e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, GOMP_FLAG) \
31690b57cec5SDimitry Andric OP_CMPXCHG_CPT_REV(TYPE, BITS, OP) \
31700b57cec5SDimitry Andric }
31710b57cec5SDimitry Andric
31720b57cec5SDimitry Andric // -------------------------------------------------------------------------
31730b57cec5SDimitry Andric #define ATOMIC_CRITICAL_CPT_REV_MIX(TYPE_ID, TYPE, OP_ID, OP, RTYPE_ID, RTYPE, \
31740b57cec5SDimitry Andric LCK_ID, GOMP_FLAG) \
31750b57cec5SDimitry Andric ATOMIC_BEGIN_CPT_MIX(TYPE_ID, OP_ID, TYPE, RTYPE_ID, RTYPE) \
31760b57cec5SDimitry Andric TYPE new_value; \
317781ad6265SDimitry Andric (void)new_value; \
3178e8d8bef9SDimitry Andric OP_GOMP_CRITICAL_CPT_REV(TYPE, OP, GOMP_FLAG) /* send assignment */ \
3179e8d8bef9SDimitry Andric OP_CRITICAL_CPT_REV(TYPE, OP, LCK_ID) /* send assignment */ \
31800b57cec5SDimitry Andric }
31810b57cec5SDimitry Andric
31820b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1, char, sub_cpt_rev, 8, -, fp, _Quad, 1i, 0,
31830b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_sub_cpt_rev_fp
31840b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1u, uchar, sub_cpt_rev, 8, -, fp, _Quad, 1i, 0,
31850b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_sub_cpt_rev_fp
31860b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1, char, div_cpt_rev, 8, /, fp, _Quad, 1i, 0,
31870b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1_div_cpt_rev_fp
31880b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed1u, uchar, div_cpt_rev, 8, /, fp, _Quad, 1i, 0,
31890b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed1u_div_cpt_rev_fp
31900b57cec5SDimitry Andric
31910b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2, short, sub_cpt_rev, 16, -, fp, _Quad, 2i, 1,
31920b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_sub_cpt_rev_fp
31930b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2u, ushort, sub_cpt_rev, 16, -, fp, _Quad, 2i,
31940b57cec5SDimitry Andric 1,
31950b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_sub_cpt_rev_fp
31960b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2, short, div_cpt_rev, 16, /, fp, _Quad, 2i, 1,
31970b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2_div_cpt_rev_fp
31980b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed2u, ushort, div_cpt_rev, 16, /, fp, _Quad, 2i,
31990b57cec5SDimitry Andric 1,
32000b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed2u_div_cpt_rev_fp
32010b57cec5SDimitry Andric
32020b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4, kmp_int32, sub_cpt_rev, 32, -, fp, _Quad, 4i,
32030b57cec5SDimitry Andric 3, 0) // __kmpc_atomic_fixed4_sub_cpt_rev_fp
32040b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4u, kmp_uint32, sub_cpt_rev, 32, -, fp, _Quad,
32050b57cec5SDimitry Andric 4i, 3, 0) // __kmpc_atomic_fixed4u_sub_cpt_rev_fp
32060b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4, kmp_int32, div_cpt_rev, 32, /, fp, _Quad, 4i,
32070b57cec5SDimitry Andric 3, 0) // __kmpc_atomic_fixed4_div_cpt_rev_fp
32080b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed4u, kmp_uint32, div_cpt_rev, 32, /, fp, _Quad,
32090b57cec5SDimitry Andric 4i, 3, 0) // __kmpc_atomic_fixed4u_div_cpt_rev_fp
32100b57cec5SDimitry Andric
32110b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8, kmp_int64, sub_cpt_rev, 64, -, fp, _Quad, 8i,
32120b57cec5SDimitry Andric 7,
32130b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_sub_cpt_rev_fp
32140b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8u, kmp_uint64, sub_cpt_rev, 64, -, fp, _Quad,
32150b57cec5SDimitry Andric 8i, 7,
32160b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_sub_cpt_rev_fp
32170b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8, kmp_int64, div_cpt_rev, 64, /, fp, _Quad, 8i,
32180b57cec5SDimitry Andric 7,
32190b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_div_cpt_rev_fp
32200b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(fixed8u, kmp_uint64, div_cpt_rev, 64, /, fp, _Quad,
32210b57cec5SDimitry Andric 8i, 7,
32220b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8u_div_cpt_rev_fp
32230b57cec5SDimitry Andric
32240b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(float4, kmp_real32, sub_cpt_rev, 32, -, fp, _Quad,
32250b57cec5SDimitry Andric 4r, 3,
32260b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_sub_cpt_rev_fp
32270b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(float4, kmp_real32, div_cpt_rev, 32, /, fp, _Quad,
32280b57cec5SDimitry Andric 4r, 3,
32290b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_div_cpt_rev_fp
32300b57cec5SDimitry Andric
32310b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(float8, kmp_real64, sub_cpt_rev, 64, -, fp, _Quad,
32320b57cec5SDimitry Andric 8r, 7,
32330b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_sub_cpt_rev_fp
32340b57cec5SDimitry Andric ATOMIC_CMPXCHG_CPT_REV_MIX(float8, kmp_real64, div_cpt_rev, 64, /, fp, _Quad,
32350b57cec5SDimitry Andric 8r, 7,
32360b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_div_cpt_rev_fp
32370b57cec5SDimitry Andric
32380b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV_MIX(float10, long double, sub_cpt_rev, -, fp, _Quad,
32390b57cec5SDimitry Andric 10r, 1) // __kmpc_atomic_float10_sub_cpt_rev_fp
32400b57cec5SDimitry Andric ATOMIC_CRITICAL_CPT_REV_MIX(float10, long double, div_cpt_rev, /, fp, _Quad,
32410b57cec5SDimitry Andric 10r, 1) // __kmpc_atomic_float10_div_cpt_rev_fp
32420b57cec5SDimitry Andric
32430b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
32440b57cec5SDimitry Andric
32450b57cec5SDimitry Andric // OpenMP 4.0 Capture-write (swap): {v = x; x = expr;}
32460b57cec5SDimitry Andric
32470b57cec5SDimitry Andric #define ATOMIC_BEGIN_SWP(TYPE_ID, TYPE) \
32480b57cec5SDimitry Andric TYPE __kmpc_atomic_##TYPE_ID##_swp(ident_t *id_ref, int gtid, TYPE *lhs, \
32490b57cec5SDimitry Andric TYPE rhs) { \
32500b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
32510b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_swp: T#%d\n", gtid));
32520b57cec5SDimitry Andric
32530b57cec5SDimitry Andric #define CRITICAL_SWP(LCK_ID) \
32540b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
32550b57cec5SDimitry Andric \
32560b57cec5SDimitry Andric old_value = (*lhs); \
32570b57cec5SDimitry Andric (*lhs) = rhs; \
32580b57cec5SDimitry Andric \
32590b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
32600b57cec5SDimitry Andric return old_value;
32610b57cec5SDimitry Andric
32620b57cec5SDimitry Andric // ------------------------------------------------------------------------
32630b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
32640b57cec5SDimitry Andric #define GOMP_CRITICAL_SWP(FLAG) \
32650b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
32660b57cec5SDimitry Andric KMP_CHECK_GTID; \
32670b57cec5SDimitry Andric CRITICAL_SWP(0); \
32680b57cec5SDimitry Andric }
32690b57cec5SDimitry Andric #else
32700b57cec5SDimitry Andric #define GOMP_CRITICAL_SWP(FLAG)
32710b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
32720b57cec5SDimitry Andric
32730b57cec5SDimitry Andric #define ATOMIC_XCHG_SWP(TYPE_ID, TYPE, BITS, GOMP_FLAG) \
32740b57cec5SDimitry Andric ATOMIC_BEGIN_SWP(TYPE_ID, TYPE) \
32750b57cec5SDimitry Andric TYPE old_value; \
32760b57cec5SDimitry Andric GOMP_CRITICAL_SWP(GOMP_FLAG) \
32770b57cec5SDimitry Andric old_value = KMP_XCHG_FIXED##BITS(lhs, rhs); \
32780b57cec5SDimitry Andric return old_value; \
32790b57cec5SDimitry Andric }
32800b57cec5SDimitry Andric // ------------------------------------------------------------------------
32810b57cec5SDimitry Andric #define ATOMIC_XCHG_FLOAT_SWP(TYPE_ID, TYPE, BITS, GOMP_FLAG) \
32820b57cec5SDimitry Andric ATOMIC_BEGIN_SWP(TYPE_ID, TYPE) \
32830b57cec5SDimitry Andric TYPE old_value; \
32840b57cec5SDimitry Andric GOMP_CRITICAL_SWP(GOMP_FLAG) \
32850b57cec5SDimitry Andric old_value = KMP_XCHG_REAL##BITS(lhs, rhs); \
32860b57cec5SDimitry Andric return old_value; \
32870b57cec5SDimitry Andric }
32880b57cec5SDimitry Andric
32890b57cec5SDimitry Andric // ------------------------------------------------------------------------
32900b57cec5SDimitry Andric #define CMPXCHG_SWP(TYPE, BITS) \
32910b57cec5SDimitry Andric { \
32920b57cec5SDimitry Andric TYPE KMP_ATOMIC_VOLATILE temp_val; \
32930b57cec5SDimitry Andric TYPE old_value, new_value; \
32940b57cec5SDimitry Andric temp_val = *lhs; \
32950b57cec5SDimitry Andric old_value = temp_val; \
32960b57cec5SDimitry Andric new_value = rhs; \
32970b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ##BITS( \
32980b57cec5SDimitry Andric (kmp_int##BITS *)lhs, *VOLATILE_CAST(kmp_int##BITS *) & old_value, \
32990b57cec5SDimitry Andric *VOLATILE_CAST(kmp_int##BITS *) & new_value)) { \
33000b57cec5SDimitry Andric temp_val = *lhs; \
33010b57cec5SDimitry Andric old_value = temp_val; \
33020b57cec5SDimitry Andric new_value = rhs; \
33030b57cec5SDimitry Andric } \
33040b57cec5SDimitry Andric return old_value; \
33050b57cec5SDimitry Andric }
33060b57cec5SDimitry Andric
33070b57cec5SDimitry Andric // -------------------------------------------------------------------------
33080b57cec5SDimitry Andric #define ATOMIC_CMPXCHG_SWP(TYPE_ID, TYPE, BITS, GOMP_FLAG) \
33090b57cec5SDimitry Andric ATOMIC_BEGIN_SWP(TYPE_ID, TYPE) \
33100b57cec5SDimitry Andric TYPE old_value; \
3311fe6060f1SDimitry Andric (void)old_value; \
33120b57cec5SDimitry Andric GOMP_CRITICAL_SWP(GOMP_FLAG) \
33130b57cec5SDimitry Andric CMPXCHG_SWP(TYPE, BITS) \
33140b57cec5SDimitry Andric }
33150b57cec5SDimitry Andric
33160b57cec5SDimitry Andric ATOMIC_XCHG_SWP(fixed1, kmp_int8, 8, KMP_ARCH_X86) // __kmpc_atomic_fixed1_swp
33170b57cec5SDimitry Andric ATOMIC_XCHG_SWP(fixed2, kmp_int16, 16, KMP_ARCH_X86) // __kmpc_atomic_fixed2_swp
33180b57cec5SDimitry Andric ATOMIC_XCHG_SWP(fixed4, kmp_int32, 32, KMP_ARCH_X86) // __kmpc_atomic_fixed4_swp
33190b57cec5SDimitry Andric
33200b57cec5SDimitry Andric ATOMIC_XCHG_FLOAT_SWP(float4, kmp_real32, 32,
33210b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float4_swp
33220b57cec5SDimitry Andric
33230b57cec5SDimitry Andric #if (KMP_ARCH_X86)
33240b57cec5SDimitry Andric ATOMIC_CMPXCHG_SWP(fixed8, kmp_int64, 64,
33250b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_fixed8_swp
33260b57cec5SDimitry Andric ATOMIC_CMPXCHG_SWP(float8, kmp_real64, 64,
33270b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_swp
33280b57cec5SDimitry Andric #else
33290b57cec5SDimitry Andric ATOMIC_XCHG_SWP(fixed8, kmp_int64, 64, KMP_ARCH_X86) // __kmpc_atomic_fixed8_swp
33300b57cec5SDimitry Andric ATOMIC_XCHG_FLOAT_SWP(float8, kmp_real64, 64,
33310b57cec5SDimitry Andric KMP_ARCH_X86) // __kmpc_atomic_float8_swp
33320b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
33330b57cec5SDimitry Andric
33340b57cec5SDimitry Andric // ------------------------------------------------------------------------
33350b57cec5SDimitry Andric // Routines for Extended types: long double, _Quad, complex flavours (use
33360b57cec5SDimitry Andric // critical section)
33370b57cec5SDimitry Andric #define ATOMIC_CRITICAL_SWP(TYPE_ID, TYPE, LCK_ID, GOMP_FLAG) \
33380b57cec5SDimitry Andric ATOMIC_BEGIN_SWP(TYPE_ID, TYPE) \
33390b57cec5SDimitry Andric TYPE old_value; \
33400b57cec5SDimitry Andric GOMP_CRITICAL_SWP(GOMP_FLAG) \
33410b57cec5SDimitry Andric CRITICAL_SWP(LCK_ID) \
33420b57cec5SDimitry Andric }
33430b57cec5SDimitry Andric
33440b57cec5SDimitry Andric // ------------------------------------------------------------------------
33450b57cec5SDimitry Andric // !!! TODO: check if we need to return void for cmplx4 routines
33460b57cec5SDimitry Andric // Workaround for cmplx4. Regular routines with return value don't work
33470b57cec5SDimitry Andric // on Win_32e. Let's return captured values through the additional parameter.
33480b57cec5SDimitry Andric
33490b57cec5SDimitry Andric #define ATOMIC_BEGIN_SWP_WRK(TYPE_ID, TYPE) \
33500b57cec5SDimitry Andric void __kmpc_atomic_##TYPE_ID##_swp(ident_t *id_ref, int gtid, TYPE *lhs, \
33510b57cec5SDimitry Andric TYPE rhs, TYPE *out) { \
33520b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial); \
33530b57cec5SDimitry Andric KA_TRACE(100, ("__kmpc_atomic_" #TYPE_ID "_swp: T#%d\n", gtid));
33540b57cec5SDimitry Andric
33550b57cec5SDimitry Andric #define CRITICAL_SWP_WRK(LCK_ID) \
33560b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
33570b57cec5SDimitry Andric \
33580b57cec5SDimitry Andric tmp = (*lhs); \
33590b57cec5SDimitry Andric (*lhs) = (rhs); \
33600b57cec5SDimitry Andric (*out) = tmp; \
33610b57cec5SDimitry Andric __kmp_release_atomic_lock(&ATOMIC_LOCK##LCK_ID, gtid); \
33620b57cec5SDimitry Andric return;
33630b57cec5SDimitry Andric // ------------------------------------------------------------------------
33640b57cec5SDimitry Andric
33650b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
33660b57cec5SDimitry Andric #define GOMP_CRITICAL_SWP_WRK(FLAG) \
33670b57cec5SDimitry Andric if ((FLAG) && (__kmp_atomic_mode == 2)) { \
33680b57cec5SDimitry Andric KMP_CHECK_GTID; \
33690b57cec5SDimitry Andric CRITICAL_SWP_WRK(0); \
33700b57cec5SDimitry Andric }
33710b57cec5SDimitry Andric #else
33720b57cec5SDimitry Andric #define GOMP_CRITICAL_SWP_WRK(FLAG)
33730b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
33740b57cec5SDimitry Andric // ------------------------------------------------------------------------
33750b57cec5SDimitry Andric
33760b57cec5SDimitry Andric #define ATOMIC_CRITICAL_SWP_WRK(TYPE_ID, TYPE, LCK_ID, GOMP_FLAG) \
33770b57cec5SDimitry Andric ATOMIC_BEGIN_SWP_WRK(TYPE_ID, TYPE) \
33780b57cec5SDimitry Andric TYPE tmp; \
33790b57cec5SDimitry Andric GOMP_CRITICAL_SWP_WRK(GOMP_FLAG) \
33800b57cec5SDimitry Andric CRITICAL_SWP_WRK(LCK_ID) \
33810b57cec5SDimitry Andric }
33820b57cec5SDimitry Andric // The end of workaround for cmplx4
33830b57cec5SDimitry Andric
33840b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(float10, long double, 10r, 1) // __kmpc_atomic_float10_swp
33850b57cec5SDimitry Andric #if KMP_HAVE_QUAD
33860b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(float16, QUAD_LEGACY, 16r, 1) // __kmpc_atomic_float16_swp
33870b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
33880b57cec5SDimitry Andric // cmplx4 routine to return void
33890b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP_WRK(cmplx4, kmp_cmplx32, 8c, 1) // __kmpc_atomic_cmplx4_swp
33900b57cec5SDimitry Andric
33910b57cec5SDimitry Andric // ATOMIC_CRITICAL_SWP( cmplx4, kmp_cmplx32, 8c, 1 ) //
33920b57cec5SDimitry Andric // __kmpc_atomic_cmplx4_swp
33930b57cec5SDimitry Andric
33940b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(cmplx8, kmp_cmplx64, 16c, 1) // __kmpc_atomic_cmplx8_swp
33950b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(cmplx10, kmp_cmplx80, 20c, 1) // __kmpc_atomic_cmplx10_swp
33960b57cec5SDimitry Andric #if KMP_HAVE_QUAD
33970b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(cmplx16, CPLX128_LEG, 32c, 1) // __kmpc_atomic_cmplx16_swp
33980b57cec5SDimitry Andric #if (KMP_ARCH_X86)
33990b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(float16_a16, Quad_a16_t, 16r,
34000b57cec5SDimitry Andric 1) // __kmpc_atomic_float16_a16_swp
34010b57cec5SDimitry Andric ATOMIC_CRITICAL_SWP(cmplx16_a16, kmp_cmplx128_a16_t, 32c,
34020b57cec5SDimitry Andric 1) // __kmpc_atomic_cmplx16_a16_swp
34030b57cec5SDimitry Andric #endif // (KMP_ARCH_X86)
34040b57cec5SDimitry Andric #endif // KMP_HAVE_QUAD
34050b57cec5SDimitry Andric
34060b57cec5SDimitry Andric // End of OpenMP 4.0 Capture
34070b57cec5SDimitry Andric
34080b57cec5SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
34090b57cec5SDimitry Andric
34100b57cec5SDimitry Andric #undef OP_CRITICAL
34110b57cec5SDimitry Andric
34120b57cec5SDimitry Andric /* ------------------------------------------------------------------------ */
34130b57cec5SDimitry Andric /* Generic atomic routines */
34140b57cec5SDimitry Andric
__kmpc_atomic_1(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))34150b57cec5SDimitry Andric void __kmpc_atomic_1(ident_t *id_ref, int gtid, void *lhs, void *rhs,
34160b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
34170b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
34180b57cec5SDimitry Andric
34190b57cec5SDimitry Andric if (
34200b57cec5SDimitry Andric #if KMP_ARCH_X86 && defined(KMP_GOMP_COMPAT)
34210b57cec5SDimitry Andric FALSE /* must use lock */
34220b57cec5SDimitry Andric #else
34230b57cec5SDimitry Andric TRUE
34240b57cec5SDimitry Andric #endif // KMP_ARCH_X86 && defined(KMP_GOMP_COMPAT)
34250b57cec5SDimitry Andric ) {
34260b57cec5SDimitry Andric kmp_int8 old_value, new_value;
34270b57cec5SDimitry Andric
34280b57cec5SDimitry Andric old_value = *(kmp_int8 *)lhs;
34290b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
34300b57cec5SDimitry Andric
34310b57cec5SDimitry Andric /* TODO: Should this be acquire or release? */
34320b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ8((kmp_int8 *)lhs, *(kmp_int8 *)&old_value,
34330b57cec5SDimitry Andric *(kmp_int8 *)&new_value)) {
34340b57cec5SDimitry Andric KMP_CPU_PAUSE();
34350b57cec5SDimitry Andric
34360b57cec5SDimitry Andric old_value = *(kmp_int8 *)lhs;
34370b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
34380b57cec5SDimitry Andric }
34390b57cec5SDimitry Andric
34400b57cec5SDimitry Andric return;
34410b57cec5SDimitry Andric } else {
34420b57cec5SDimitry Andric // All 1-byte data is of integer data type.
34430b57cec5SDimitry Andric
34440b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
34450b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
34460b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
34470b57cec5SDimitry Andric } else
34480b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
34490b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_1i, gtid);
34500b57cec5SDimitry Andric
34510b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
34520b57cec5SDimitry Andric
34530b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
34540b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
34550b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
34560b57cec5SDimitry Andric } else
34570b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
34580b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_1i, gtid);
34590b57cec5SDimitry Andric }
34600b57cec5SDimitry Andric }
34610b57cec5SDimitry Andric
__kmpc_atomic_2(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))34620b57cec5SDimitry Andric void __kmpc_atomic_2(ident_t *id_ref, int gtid, void *lhs, void *rhs,
34630b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
34640b57cec5SDimitry Andric if (
34650b57cec5SDimitry Andric #if KMP_ARCH_X86 && defined(KMP_GOMP_COMPAT)
34660b57cec5SDimitry Andric FALSE /* must use lock */
34670b57cec5SDimitry Andric #elif KMP_ARCH_X86 || KMP_ARCH_X86_64
34680b57cec5SDimitry Andric TRUE /* no alignment problems */
34690b57cec5SDimitry Andric #else
34700b57cec5SDimitry Andric !((kmp_uintptr_t)lhs & 0x1) /* make sure address is 2-byte aligned */
34710b57cec5SDimitry Andric #endif // KMP_ARCH_X86 && defined(KMP_GOMP_COMPAT)
34720b57cec5SDimitry Andric ) {
34730b57cec5SDimitry Andric kmp_int16 old_value, new_value;
34740b57cec5SDimitry Andric
34750b57cec5SDimitry Andric old_value = *(kmp_int16 *)lhs;
34760b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
34770b57cec5SDimitry Andric
34780b57cec5SDimitry Andric /* TODO: Should this be acquire or release? */
34790b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ16(
34800b57cec5SDimitry Andric (kmp_int16 *)lhs, *(kmp_int16 *)&old_value, *(kmp_int16 *)&new_value)) {
34810b57cec5SDimitry Andric KMP_CPU_PAUSE();
34820b57cec5SDimitry Andric
34830b57cec5SDimitry Andric old_value = *(kmp_int16 *)lhs;
34840b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
34850b57cec5SDimitry Andric }
34860b57cec5SDimitry Andric
34870b57cec5SDimitry Andric return;
34880b57cec5SDimitry Andric } else {
34890b57cec5SDimitry Andric // All 2-byte data is of integer data type.
34900b57cec5SDimitry Andric
34910b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
34920b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
34930b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
34940b57cec5SDimitry Andric } else
34950b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
34960b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_2i, gtid);
34970b57cec5SDimitry Andric
34980b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
34990b57cec5SDimitry Andric
35000b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
35010b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
35020b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
35030b57cec5SDimitry Andric } else
35040b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
35050b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_2i, gtid);
35060b57cec5SDimitry Andric }
35070b57cec5SDimitry Andric }
35080b57cec5SDimitry Andric
__kmpc_atomic_4(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))35090b57cec5SDimitry Andric void __kmpc_atomic_4(ident_t *id_ref, int gtid, void *lhs, void *rhs,
35100b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
35110b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
35120b57cec5SDimitry Andric
35130b57cec5SDimitry Andric if (
35140b57cec5SDimitry Andric // FIXME: On IA-32 architecture, gcc uses cmpxchg only for 4-byte ints.
35150b57cec5SDimitry Andric // Gomp compatibility is broken if this routine is called for floats.
35160b57cec5SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
35170b57cec5SDimitry Andric TRUE /* no alignment problems */
35180b57cec5SDimitry Andric #else
35190b57cec5SDimitry Andric !((kmp_uintptr_t)lhs & 0x3) /* make sure address is 4-byte aligned */
35200b57cec5SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
35210b57cec5SDimitry Andric ) {
35220b57cec5SDimitry Andric kmp_int32 old_value, new_value;
35230b57cec5SDimitry Andric
35240b57cec5SDimitry Andric old_value = *(kmp_int32 *)lhs;
35250b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
35260b57cec5SDimitry Andric
35270b57cec5SDimitry Andric /* TODO: Should this be acquire or release? */
35280b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ32(
35290b57cec5SDimitry Andric (kmp_int32 *)lhs, *(kmp_int32 *)&old_value, *(kmp_int32 *)&new_value)) {
35300b57cec5SDimitry Andric KMP_CPU_PAUSE();
35310b57cec5SDimitry Andric
35320b57cec5SDimitry Andric old_value = *(kmp_int32 *)lhs;
35330b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
35340b57cec5SDimitry Andric }
35350b57cec5SDimitry Andric
35360b57cec5SDimitry Andric return;
35370b57cec5SDimitry Andric } else {
35380b57cec5SDimitry Andric // Use __kmp_atomic_lock_4i for all 4-byte data,
35390b57cec5SDimitry Andric // even if it isn't of integer data type.
35400b57cec5SDimitry Andric
35410b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
35420b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
35430b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
35440b57cec5SDimitry Andric } else
35450b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
35460b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_4i, gtid);
35470b57cec5SDimitry Andric
35480b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
35490b57cec5SDimitry Andric
35500b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
35510b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
35520b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
35530b57cec5SDimitry Andric } else
35540b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
35550b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_4i, gtid);
35560b57cec5SDimitry Andric }
35570b57cec5SDimitry Andric }
35580b57cec5SDimitry Andric
__kmpc_atomic_8(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))35590b57cec5SDimitry Andric void __kmpc_atomic_8(ident_t *id_ref, int gtid, void *lhs, void *rhs,
35600b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
35610b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
35620b57cec5SDimitry Andric if (
35630b57cec5SDimitry Andric
35640b57cec5SDimitry Andric #if KMP_ARCH_X86 && defined(KMP_GOMP_COMPAT)
35650b57cec5SDimitry Andric FALSE /* must use lock */
35660b57cec5SDimitry Andric #elif KMP_ARCH_X86 || KMP_ARCH_X86_64
35670b57cec5SDimitry Andric TRUE /* no alignment problems */
35680b57cec5SDimitry Andric #else
35690b57cec5SDimitry Andric !((kmp_uintptr_t)lhs & 0x7) /* make sure address is 8-byte aligned */
35700b57cec5SDimitry Andric #endif // KMP_ARCH_X86 && defined(KMP_GOMP_COMPAT)
35710b57cec5SDimitry Andric ) {
35720b57cec5SDimitry Andric kmp_int64 old_value, new_value;
35730b57cec5SDimitry Andric
35740b57cec5SDimitry Andric old_value = *(kmp_int64 *)lhs;
35750b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
35760b57cec5SDimitry Andric /* TODO: Should this be acquire or release? */
35770b57cec5SDimitry Andric while (!KMP_COMPARE_AND_STORE_ACQ64(
35780b57cec5SDimitry Andric (kmp_int64 *)lhs, *(kmp_int64 *)&old_value, *(kmp_int64 *)&new_value)) {
35790b57cec5SDimitry Andric KMP_CPU_PAUSE();
35800b57cec5SDimitry Andric
35810b57cec5SDimitry Andric old_value = *(kmp_int64 *)lhs;
35820b57cec5SDimitry Andric (*f)(&new_value, &old_value, rhs);
35830b57cec5SDimitry Andric }
35840b57cec5SDimitry Andric
35850b57cec5SDimitry Andric return;
35860b57cec5SDimitry Andric } else {
35870b57cec5SDimitry Andric // Use __kmp_atomic_lock_8i for all 8-byte data,
35880b57cec5SDimitry Andric // even if it isn't of integer data type.
35890b57cec5SDimitry Andric
35900b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
35910b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
35920b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
35930b57cec5SDimitry Andric } else
35940b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
35950b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_8i, gtid);
35960b57cec5SDimitry Andric
35970b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
35980b57cec5SDimitry Andric
35990b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36000b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36010b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
36020b57cec5SDimitry Andric } else
36030b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36040b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_8i, gtid);
36050b57cec5SDimitry Andric }
36060b57cec5SDimitry Andric }
360704eeddc0SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
__kmpc_atomic_10(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))36080b57cec5SDimitry Andric void __kmpc_atomic_10(ident_t *id_ref, int gtid, void *lhs, void *rhs,
36090b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
36100b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
36110b57cec5SDimitry Andric
36120b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36130b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36140b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
36150b57cec5SDimitry Andric } else
36160b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36170b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_10r, gtid);
36180b57cec5SDimitry Andric
36190b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
36200b57cec5SDimitry Andric
36210b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36220b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36230b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
36240b57cec5SDimitry Andric } else
36250b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36260b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_10r, gtid);
36270b57cec5SDimitry Andric }
362804eeddc0SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
36290b57cec5SDimitry Andric
__kmpc_atomic_16(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))36300b57cec5SDimitry Andric void __kmpc_atomic_16(ident_t *id_ref, int gtid, void *lhs, void *rhs,
36310b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
36320b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
36330b57cec5SDimitry Andric
36340b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36350b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36360b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
36370b57cec5SDimitry Andric } else
36380b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36390b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_16c, gtid);
36400b57cec5SDimitry Andric
36410b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
36420b57cec5SDimitry Andric
36430b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36440b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36450b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
36460b57cec5SDimitry Andric } else
36470b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36480b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_16c, gtid);
36490b57cec5SDimitry Andric }
365004eeddc0SDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
__kmpc_atomic_20(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))36510b57cec5SDimitry Andric void __kmpc_atomic_20(ident_t *id_ref, int gtid, void *lhs, void *rhs,
36520b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
36530b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
36540b57cec5SDimitry Andric
36550b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36560b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36570b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
36580b57cec5SDimitry Andric } else
36590b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36600b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_20c, gtid);
36610b57cec5SDimitry Andric
36620b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
36630b57cec5SDimitry Andric
36640b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36650b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36660b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
36670b57cec5SDimitry Andric } else
36680b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36690b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_20c, gtid);
36700b57cec5SDimitry Andric }
367104eeddc0SDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
__kmpc_atomic_32(ident_t * id_ref,int gtid,void * lhs,void * rhs,void (* f)(void *,void *,void *))36720b57cec5SDimitry Andric void __kmpc_atomic_32(ident_t *id_ref, int gtid, void *lhs, void *rhs,
36730b57cec5SDimitry Andric void (*f)(void *, void *, void *)) {
36740b57cec5SDimitry Andric KMP_DEBUG_ASSERT(__kmp_init_serial);
36750b57cec5SDimitry Andric
36760b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36770b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36780b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
36790b57cec5SDimitry Andric } else
36800b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36810b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock_32c, gtid);
36820b57cec5SDimitry Andric
36830b57cec5SDimitry Andric (*f)(lhs, lhs, rhs);
36840b57cec5SDimitry Andric
36850b57cec5SDimitry Andric #ifdef KMP_GOMP_COMPAT
36860b57cec5SDimitry Andric if (__kmp_atomic_mode == 2) {
36870b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
36880b57cec5SDimitry Andric } else
36890b57cec5SDimitry Andric #endif /* KMP_GOMP_COMPAT */
36900b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock_32c, gtid);
36910b57cec5SDimitry Andric }
36920b57cec5SDimitry Andric
36930b57cec5SDimitry Andric // AC: same two routines as GOMP_atomic_start/end, but will be called by our
36940b57cec5SDimitry Andric // compiler; duplicated in order to not use 3-party names in pure Intel code
36950b57cec5SDimitry Andric // TODO: consider adding GTID parameter after consultation with Ernesto/Xinmin.
__kmpc_atomic_start(void)36960b57cec5SDimitry Andric void __kmpc_atomic_start(void) {
36970b57cec5SDimitry Andric int gtid = __kmp_entry_gtid();
36980b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_atomic_start: T#%d\n", gtid));
36990b57cec5SDimitry Andric __kmp_acquire_atomic_lock(&__kmp_atomic_lock, gtid);
37000b57cec5SDimitry Andric }
37010b57cec5SDimitry Andric
__kmpc_atomic_end(void)37020b57cec5SDimitry Andric void __kmpc_atomic_end(void) {
37030b57cec5SDimitry Andric int gtid = __kmp_get_gtid();
37040b57cec5SDimitry Andric KA_TRACE(20, ("__kmpc_atomic_end: T#%d\n", gtid));
37050b57cec5SDimitry Andric __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid);
37060b57cec5SDimitry Andric }
37070b57cec5SDimitry Andric
3708349cc55cSDimitry Andric #if KMP_ARCH_X86 || KMP_ARCH_X86_64
3709349cc55cSDimitry Andric
3710349cc55cSDimitry Andric // OpenMP 5.1 compare and swap
3711349cc55cSDimitry Andric
3712349cc55cSDimitry Andric /*!
3713349cc55cSDimitry Andric @param loc Source code location
3714349cc55cSDimitry Andric @param gtid Global thread id
3715349cc55cSDimitry Andric @param x Memory location to operate on
3716349cc55cSDimitry Andric @param e Expected value
3717349cc55cSDimitry Andric @param d Desired value
3718349cc55cSDimitry Andric @return Result of comparison
3719349cc55cSDimitry Andric
3720349cc55cSDimitry Andric Implements Compare And Swap atomic operation.
3721349cc55cSDimitry Andric
3722349cc55cSDimitry Andric Sample code:
3723349cc55cSDimitry Andric #pragma omp atomic compare update capture
3724349cc55cSDimitry Andric { r = x == e; if(r) { x = d; } }
3725349cc55cSDimitry Andric */
__kmpc_atomic_bool_1_cas(ident_t * loc,int gtid,char * x,char e,char d)3726349cc55cSDimitry Andric bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d) {
3727349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_ACQ8(x, e, d);
3728349cc55cSDimitry Andric }
__kmpc_atomic_bool_2_cas(ident_t * loc,int gtid,short * x,short e,short d)3729349cc55cSDimitry Andric bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e,
3730349cc55cSDimitry Andric short d) {
3731349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_ACQ16(x, e, d);
3732349cc55cSDimitry Andric }
__kmpc_atomic_bool_4_cas(ident_t * loc,int gtid,kmp_int32 * x,kmp_int32 e,kmp_int32 d)3733349cc55cSDimitry Andric bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e,
3734349cc55cSDimitry Andric kmp_int32 d) {
3735349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_ACQ32(x, e, d);
3736349cc55cSDimitry Andric }
__kmpc_atomic_bool_8_cas(ident_t * loc,int gtid,kmp_int64 * x,kmp_int64 e,kmp_int64 d)3737349cc55cSDimitry Andric bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e,
3738349cc55cSDimitry Andric kmp_int64 d) {
3739349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_ACQ64(x, e, d);
3740349cc55cSDimitry Andric }
3741349cc55cSDimitry Andric
3742349cc55cSDimitry Andric /*!
3743349cc55cSDimitry Andric @param loc Source code location
3744349cc55cSDimitry Andric @param gtid Global thread id
3745349cc55cSDimitry Andric @param x Memory location to operate on
3746349cc55cSDimitry Andric @param e Expected value
3747349cc55cSDimitry Andric @param d Desired value
3748349cc55cSDimitry Andric @return Old value of x
3749349cc55cSDimitry Andric
3750349cc55cSDimitry Andric Implements Compare And Swap atomic operation.
3751349cc55cSDimitry Andric
3752349cc55cSDimitry Andric Sample code:
3753349cc55cSDimitry Andric #pragma omp atomic compare update capture
3754349cc55cSDimitry Andric { v = x; if (x == e) { x = d; } }
3755349cc55cSDimitry Andric */
__kmpc_atomic_val_1_cas(ident_t * loc,int gtid,char * x,char e,char d)3756349cc55cSDimitry Andric char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d) {
3757349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_RET8(x, e, d);
3758349cc55cSDimitry Andric }
__kmpc_atomic_val_2_cas(ident_t * loc,int gtid,short * x,short e,short d)3759349cc55cSDimitry Andric short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e,
3760349cc55cSDimitry Andric short d) {
3761349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_RET16(x, e, d);
3762349cc55cSDimitry Andric }
__kmpc_atomic_val_4_cas(ident_t * loc,int gtid,kmp_int32 * x,kmp_int32 e,kmp_int32 d)3763349cc55cSDimitry Andric kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x,
3764349cc55cSDimitry Andric kmp_int32 e, kmp_int32 d) {
3765349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_RET32(x, e, d);
3766349cc55cSDimitry Andric }
__kmpc_atomic_val_8_cas(ident_t * loc,int gtid,kmp_int64 * x,kmp_int64 e,kmp_int64 d)3767349cc55cSDimitry Andric kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x,
3768349cc55cSDimitry Andric kmp_int64 e, kmp_int64 d) {
3769349cc55cSDimitry Andric return KMP_COMPARE_AND_STORE_RET64(x, e, d);
3770349cc55cSDimitry Andric }
3771349cc55cSDimitry Andric
3772349cc55cSDimitry Andric /*!
3773349cc55cSDimitry Andric @param loc Source code location
3774349cc55cSDimitry Andric @param gtid Global thread id
3775349cc55cSDimitry Andric @param x Memory location to operate on
3776349cc55cSDimitry Andric @param e Expected value
3777349cc55cSDimitry Andric @param d Desired value
3778349cc55cSDimitry Andric @param pv Captured value location
3779349cc55cSDimitry Andric @return Result of comparison
3780349cc55cSDimitry Andric
3781349cc55cSDimitry Andric Implements Compare And Swap + Capture atomic operation.
3782349cc55cSDimitry Andric
3783349cc55cSDimitry Andric v gets old valie of x if comparison failed, untouched otherwise.
3784349cc55cSDimitry Andric Sample code:
3785349cc55cSDimitry Andric #pragma omp atomic compare update capture
3786349cc55cSDimitry Andric { r = x == e; if(r) { x = d; } else { v = x; } }
3787349cc55cSDimitry Andric */
__kmpc_atomic_bool_1_cas_cpt(ident_t * loc,int gtid,char * x,char e,char d,char * pv)3788349cc55cSDimitry Andric bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
3789349cc55cSDimitry Andric char d, char *pv) {
3790349cc55cSDimitry Andric char old = KMP_COMPARE_AND_STORE_RET8(x, e, d);
3791349cc55cSDimitry Andric if (old == e)
3792349cc55cSDimitry Andric return true;
3793349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3794349cc55cSDimitry Andric *pv = old;
3795349cc55cSDimitry Andric return false;
3796349cc55cSDimitry Andric }
__kmpc_atomic_bool_2_cas_cpt(ident_t * loc,int gtid,short * x,short e,short d,short * pv)3797349cc55cSDimitry Andric bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
3798349cc55cSDimitry Andric short d, short *pv) {
3799349cc55cSDimitry Andric short old = KMP_COMPARE_AND_STORE_RET16(x, e, d);
3800349cc55cSDimitry Andric if (old == e)
3801349cc55cSDimitry Andric return true;
3802349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3803349cc55cSDimitry Andric *pv = old;
3804349cc55cSDimitry Andric return false;
3805349cc55cSDimitry Andric }
__kmpc_atomic_bool_4_cas_cpt(ident_t * loc,int gtid,kmp_int32 * x,kmp_int32 e,kmp_int32 d,kmp_int32 * pv)3806349cc55cSDimitry Andric bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
3807349cc55cSDimitry Andric kmp_int32 e, kmp_int32 d, kmp_int32 *pv) {
3808349cc55cSDimitry Andric kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d);
3809349cc55cSDimitry Andric if (old == e)
3810349cc55cSDimitry Andric return true;
3811349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3812349cc55cSDimitry Andric *pv = old;
3813349cc55cSDimitry Andric return false;
3814349cc55cSDimitry Andric }
__kmpc_atomic_bool_8_cas_cpt(ident_t * loc,int gtid,kmp_int64 * x,kmp_int64 e,kmp_int64 d,kmp_int64 * pv)3815349cc55cSDimitry Andric bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
3816349cc55cSDimitry Andric kmp_int64 e, kmp_int64 d, kmp_int64 *pv) {
3817349cc55cSDimitry Andric kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d);
3818349cc55cSDimitry Andric if (old == e)
3819349cc55cSDimitry Andric return true;
3820349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3821349cc55cSDimitry Andric *pv = old;
3822349cc55cSDimitry Andric return false;
3823349cc55cSDimitry Andric }
3824349cc55cSDimitry Andric
3825349cc55cSDimitry Andric /*!
3826349cc55cSDimitry Andric @param loc Source code location
3827349cc55cSDimitry Andric @param gtid Global thread id
3828349cc55cSDimitry Andric @param x Memory location to operate on
3829349cc55cSDimitry Andric @param e Expected value
3830349cc55cSDimitry Andric @param d Desired value
3831349cc55cSDimitry Andric @param pv Captured value location
3832349cc55cSDimitry Andric @return Old value of x
3833349cc55cSDimitry Andric
3834349cc55cSDimitry Andric Implements Compare And Swap + Capture atomic operation.
3835349cc55cSDimitry Andric
3836349cc55cSDimitry Andric v gets new valie of x.
3837349cc55cSDimitry Andric Sample code:
3838349cc55cSDimitry Andric #pragma omp atomic compare update capture
3839349cc55cSDimitry Andric { if (x == e) { x = d; }; v = x; }
3840349cc55cSDimitry Andric */
__kmpc_atomic_val_1_cas_cpt(ident_t * loc,int gtid,char * x,char e,char d,char * pv)3841349cc55cSDimitry Andric char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e,
3842349cc55cSDimitry Andric char d, char *pv) {
3843349cc55cSDimitry Andric char old = KMP_COMPARE_AND_STORE_RET8(x, e, d);
3844349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3845349cc55cSDimitry Andric *pv = old == e ? d : old;
3846349cc55cSDimitry Andric return old;
3847349cc55cSDimitry Andric }
__kmpc_atomic_val_2_cas_cpt(ident_t * loc,int gtid,short * x,short e,short d,short * pv)3848349cc55cSDimitry Andric short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e,
3849349cc55cSDimitry Andric short d, short *pv) {
3850349cc55cSDimitry Andric short old = KMP_COMPARE_AND_STORE_RET16(x, e, d);
3851349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3852349cc55cSDimitry Andric *pv = old == e ? d : old;
3853349cc55cSDimitry Andric return old;
3854349cc55cSDimitry Andric }
__kmpc_atomic_val_4_cas_cpt(ident_t * loc,int gtid,kmp_int32 * x,kmp_int32 e,kmp_int32 d,kmp_int32 * pv)3855349cc55cSDimitry Andric kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x,
3856349cc55cSDimitry Andric kmp_int32 e, kmp_int32 d, kmp_int32 *pv) {
3857349cc55cSDimitry Andric kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d);
3858349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3859349cc55cSDimitry Andric *pv = old == e ? d : old;
3860349cc55cSDimitry Andric return old;
3861349cc55cSDimitry Andric }
__kmpc_atomic_val_8_cas_cpt(ident_t * loc,int gtid,kmp_int64 * x,kmp_int64 e,kmp_int64 d,kmp_int64 * pv)3862349cc55cSDimitry Andric kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x,
3863349cc55cSDimitry Andric kmp_int64 e, kmp_int64 d, kmp_int64 *pv) {
3864349cc55cSDimitry Andric kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d);
3865349cc55cSDimitry Andric KMP_ASSERT(pv != NULL);
3866349cc55cSDimitry Andric *pv = old == e ? d : old;
3867349cc55cSDimitry Andric return old;
3868349cc55cSDimitry Andric }
3869349cc55cSDimitry Andric
3870349cc55cSDimitry Andric // End OpenMP 5.1 compare + capture
3871349cc55cSDimitry Andric #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
3872349cc55cSDimitry Andric
38730b57cec5SDimitry Andric /*!
38740b57cec5SDimitry Andric @}
38750b57cec5SDimitry Andric */
38760b57cec5SDimitry Andric
38770b57cec5SDimitry Andric // end of file
3878