diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports --- a/openmp/runtime/src/dllexports +++ b/openmp/runtime/src/dllexports @@ -1218,6 +1218,29 @@ __kmpc_atomic_fixed8u_mul_fp %endif + # OpenMP 5.1 atomics + __kmpc_atomic_float10_max 2139 + __kmpc_atomic_float10_min 2140 + __kmpc_atomic_float10_max_cpt 2141 + __kmpc_atomic_float10_min_cpt 2142 + + __kmpc_atomic_bool_1_cas 2143 + __kmpc_atomic_bool_2_cas 2144 + __kmpc_atomic_bool_4_cas 2145 + __kmpc_atomic_bool_8_cas 2146 + __kmpc_atomic_val_1_cas 2147 + __kmpc_atomic_val_2_cas 2148 + __kmpc_atomic_val_4_cas 2149 + __kmpc_atomic_val_8_cas 2150 + __kmpc_atomic_bool_1_cas_cpt 2151 + __kmpc_atomic_bool_2_cas_cpt 2152 + __kmpc_atomic_bool_4_cas_cpt 2153 + __kmpc_atomic_bool_8_cas_cpt 2154 + __kmpc_atomic_val_1_cas_cpt 2155 + __kmpc_atomic_val_2_cas_cpt 2156 + __kmpc_atomic_val_4_cas_cpt 2157 + __kmpc_atomic_val_8_cas_cpt 2158 + %endif # end of file # diff --git a/openmp/runtime/src/kmp_atomic.h b/openmp/runtime/src/kmp_atomic.h --- a/openmp/runtime/src/kmp_atomic.h +++ b/openmp/runtime/src/kmp_atomic.h @@ -578,6 +578,10 @@ kmp_real64 rhs); void __kmpc_atomic_float8_min(ident_t *id_ref, int gtid, kmp_real64 *lhs, kmp_real64 rhs); +void __kmpc_atomic_float10_max(ident_t *id_ref, int gtid, long double *lhs, + long double rhs); +void __kmpc_atomic_float10_min(ident_t *id_ref, int gtid, long double *lhs, + long double rhs); #if KMP_HAVE_QUAD void __kmpc_atomic_float16_max(ident_t *id_ref, int gtid, QUAD_LEGACY *lhs, QUAD_LEGACY rhs); @@ -1254,6 +1258,12 @@ kmp_real64 __kmpc_atomic_float8_min_cpt(ident_t *id_ref, int gtid, kmp_real64 *lhs, kmp_real64 rhs, int flag); +long double __kmpc_atomic_float10_max_cpt(ident_t *id_ref, int gtid, + long double *lhs, long double rhs, + int flag); +long double __kmpc_atomic_float10_min_cpt(ident_t *id_ref, int gtid, + long double *lhs, long double rhs, + int flag); #if KMP_HAVE_QUAD QUAD_LEGACY __kmpc_atomic_float16_max_cpt(ident_t *id_ref, int gtid, QUAD_LEGACY *lhs, QUAD_LEGACY rhs, @@ -1756,6 +1766,78 @@ // End of OpenMP 4.0 capture +// OpenMP 5.1 compare and swap +/* + __kmpc_atomic_bool_1_cas + __kmpc_atomic_bool_2_cas + __kmpc_atomic_bool_4_cas + __kmpc_atomic_bool_8_cas + __kmpc_atomic_val_1_cas + __kmpc_atomic_val_2_cas + __kmpc_atomic_val_4_cas + __kmpc_atomic_val_8_cas + __kmpc_atomic_bool_1_cas_cpt + __kmpc_atomic_bool_2_cas_cpt + __kmpc_atomic_bool_4_cas_cpt + __kmpc_atomic_bool_8_cas_cpt + __kmpc_atomic_val_1_cas_cpt + __kmpc_atomic_val_2_cas_cpt + __kmpc_atomic_val_4_cas_cpt + __kmpc_atomic_val_8_cas_cpt +*/ +// In all interfaces of CAS (Compare And Swap): +// r is the boolean result of comparison +// x is memory location to operate on +// e is expected (old) value +// d is desired (new) value +// pv is pointer to captured value v whose location may coincide with e + +// { r = x == e; if(r) { x = d; } } +// functions return result of comparison +bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d); +bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, + short d); +bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e, + kmp_int32 d); +bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e, + kmp_int64 d); + +// { v = x; if (x == e) { x = d; } } +// functions return old value +char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d); +short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, + short d); +kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x, + kmp_int32 e, kmp_int32 d); +kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x, + kmp_int64 e, kmp_int64 d); + +// { r = x == e; if(r) { x = d; } else { v = x; } } +// v gets old value if comparison failed, untouched otherwise +// functions return result of comparison +bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, + char d, char *pv); +bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, + short d, short *pv); +bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x, + kmp_int32 e, kmp_int32 d, kmp_int32 *pv); +bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x, + kmp_int64 e, kmp_int64 d, kmp_int64 *pv); + +// { if (x == e) { x = d; }; v = x; } +// v gets old value if comparison failed, new value otherwise +// functions return old value +char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, + char d, char *pv); +short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, + short d, short *pv); +kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x, + kmp_int32 e, kmp_int32 d, kmp_int32 *pv); +kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x, + kmp_int64 e, kmp_int64 d, kmp_int64 *pv); + +// End OpenMP 5.1 compare + capture + #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64 /* ------------------------------------------------------------------------ */ diff --git a/openmp/runtime/src/kmp_atomic.cpp b/openmp/runtime/src/kmp_atomic.cpp --- a/openmp/runtime/src/kmp_atomic.cpp +++ b/openmp/runtime/src/kmp_atomic.cpp @@ -1235,6 +1235,10 @@ KMP_ARCH_X86) // __kmpc_atomic_float8_max MIN_MAX_COMPXCHG(float8, min, kmp_real64, 64, >, 8r, 7, KMP_ARCH_X86) // __kmpc_atomic_float8_min +MIN_MAX_CRITICAL(float10, max, long double, <, 10r, + 1) // __kmpc_atomic_float10_max +MIN_MAX_CRITICAL(float10, min, long double, >, 10r, + 1) // __kmpc_atomic_float10_min #if KMP_HAVE_QUAD MIN_MAX_CRITICAL(float16, max, QUAD_LEGACY, <, 16r, 1) // __kmpc_atomic_float16_max @@ -2717,6 +2721,10 @@ KMP_ARCH_X86) // __kmpc_atomic_float8_max_cpt MIN_MAX_COMPXCHG_CPT(float8, min_cpt, kmp_real64, 64, >, KMP_ARCH_X86) // __kmpc_atomic_float8_min_cpt +MIN_MAX_CRITICAL_CPT(float10, max_cpt, long double, <, 10r, + 1) // __kmpc_atomic_float10_max_cpt +MIN_MAX_CRITICAL_CPT(float10, min_cpt, long double, >, 10r, + 1) // __kmpc_atomic_float10_min_cpt #if KMP_HAVE_QUAD MIN_MAX_CRITICAL_CPT(float16, max_cpt, QUAD_LEGACY, <, 16r, 1) // __kmpc_atomic_float16_max_cpt @@ -3686,6 +3694,168 @@ __kmp_release_atomic_lock(&__kmp_atomic_lock, gtid); } +// OpenMP 5.1 compare and swap + +/*! +@param loc Source code location +@param gtid Global thread id +@param x Memory location to operate on +@param e Expected value +@param d Desired value +@return Result of comparison + +Implements Compare And Swap atomic operation. + +Sample code: +#pragma omp atomic compare update capture + { r = x == e; if(r) { x = d; } } +*/ +bool __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d) { + return KMP_COMPARE_AND_STORE_ACQ8(x, e, d); +} +bool __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, + short d) { + return KMP_COMPARE_AND_STORE_ACQ16(x, e, d); +} +bool __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, kmp_int32 *x, kmp_int32 e, + kmp_int32 d) { + return KMP_COMPARE_AND_STORE_ACQ32(x, e, d); +} +bool __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, kmp_int64 *x, kmp_int64 e, + kmp_int64 d) { + return KMP_COMPARE_AND_STORE_ACQ64(x, e, d); +} + +/*! +@param loc Source code location +@param gtid Global thread id +@param x Memory location to operate on +@param e Expected value +@param d Desired value +@return Old value of x + +Implements Compare And Swap atomic operation. + +Sample code: +#pragma omp atomic compare update capture + { v = x; if (x == e) { x = d; } } +*/ +char __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d) { + return KMP_COMPARE_AND_STORE_RET8(x, e, d); +} +short __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, + short d) { + return KMP_COMPARE_AND_STORE_RET16(x, e, d); +} +kmp_int32 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, kmp_int32 *x, + kmp_int32 e, kmp_int32 d) { + return KMP_COMPARE_AND_STORE_RET32(x, e, d); +} +kmp_int64 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, kmp_int64 *x, + kmp_int64 e, kmp_int64 d) { + return KMP_COMPARE_AND_STORE_RET64(x, e, d); +} + +/*! +@param loc Source code location +@param gtid Global thread id +@param x Memory location to operate on +@param e Expected value +@param d Desired value +@param pv Captured value location +@return Result of comparison + +Implements Compare And Swap + Capture atomic operation. + +v gets old valie of x if comparison failed, untouched otherwise. +Sample code: +#pragma omp atomic compare update capture + { r = x == e; if(r) { x = d; } else { v = x; } } +*/ +bool __kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, + char d, char *pv) { + char old = KMP_COMPARE_AND_STORE_RET8(x, e, d); + if (old == e) + return true; + KMP_ASSERT(pv != NULL); + *pv = old; + return false; +} +bool __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, + short d, short *pv) { + short old = KMP_COMPARE_AND_STORE_RET16(x, e, d); + if (old == e) + return true; + KMP_ASSERT(pv != NULL); + *pv = old; + return false; +} +bool __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x, + kmp_int32 e, kmp_int32 d, kmp_int32 *pv) { + kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d); + if (old == e) + return true; + KMP_ASSERT(pv != NULL); + *pv = old; + return false; +} +bool __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x, + kmp_int64 e, kmp_int64 d, kmp_int64 *pv) { + kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d); + if (old == e) + return true; + KMP_ASSERT(pv != NULL); + *pv = old; + return false; +} + +/*! +@param loc Source code location +@param gtid Global thread id +@param x Memory location to operate on +@param e Expected value +@param d Desired value +@param pv Captured value location +@return Old value of x + +Implements Compare And Swap + Capture atomic operation. + +v gets new valie of x. +Sample code: +#pragma omp atomic compare update capture + { if (x == e) { x = d; }; v = x; } +*/ +char __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, + char d, char *pv) { + char old = KMP_COMPARE_AND_STORE_RET8(x, e, d); + KMP_ASSERT(pv != NULL); + *pv = old == e ? d : old; + return old; +} +short __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, + short d, short *pv) { + short old = KMP_COMPARE_AND_STORE_RET16(x, e, d); + KMP_ASSERT(pv != NULL); + *pv = old == e ? d : old; + return old; +} +kmp_int32 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, kmp_int32 *x, + kmp_int32 e, kmp_int32 d, kmp_int32 *pv) { + kmp_int32 old = KMP_COMPARE_AND_STORE_RET32(x, e, d); + KMP_ASSERT(pv != NULL); + *pv = old == e ? d : old; + return old; +} +kmp_int64 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, kmp_int64 *x, + kmp_int64 e, kmp_int64 d, kmp_int64 *pv) { + kmp_int64 old = KMP_COMPARE_AND_STORE_RET64(x, e, d); + KMP_ASSERT(pv != NULL); + *pv = old == e ? d : old; + return old; +} + +// End OpenMP 5.1 compare + capture + /*! @} */ diff --git a/openmp/runtime/test/atomic/kmp_atomic_cas.c b/openmp/runtime/test/atomic/kmp_atomic_cas.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/atomic/kmp_atomic_cas.c @@ -0,0 +1,180 @@ +// RUN: %libomp-compile-and-run + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef void* ident_t; +extern bool +__kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d); +extern bool +__kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, short d); +extern bool +__kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, int *x, int e, int d); +extern bool +__kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, long long *x, long long e, + long long d); +extern char +__kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d); +extern short +__kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, short d); +extern int +__kmpc_atomic_val_4_cas(ident_t *loc, int gtid, int *x, int e, int d); +extern long long +__kmpc_atomic_val_8_cas(ident_t *loc, int gtid, long long *x, long long e, + long long d); +#ifdef __cplusplus +} +#endif + +int main() { + int ret = 0; + bool r; + char c0 = 1; + char c1 = 2; + char c2 = 3; + char co = 2; + char cc = 0; + short s0 = 11; + short s1 = 12; + short s2 = 13; + short so = 12; + short sc = 0; + int i0 = 211; + int i1 = 212; + int i2 = 213; + int io = 212; + int ic = 0; + long long l0 = 3111; + long long l1 = 3112; + long long l2 = 3113; + long long lo = 3112; + long long lc = 0; + +// initialize OpenMP runtime library + omp_set_dynamic(0); + +// #pragma omp atomic compare update capture +// { r = x == e; if(r) { x = d; } } +// char, co == c1 initially, co == c2 finally + r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c0, c2); // no-op + if (co != c1) { + ret++; printf("Error bool_1_cas no-op: %d != %d\n", co, c1); } + if (r) { ret++; printf("Error bool_1_cas no-op ret: %d\n", r); } + r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c1, c2); + if (co != c2) { + ret++; printf("Error bool_1_cas: %d != %d\n", co, c2); } + if (!r) { ret++; printf("Error bool_1_cas ret: %d\n", r); } +// short + r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s0, s2); // no-op + if (so != s1) { + ret++; printf("Error bool_2_cas no-op: %d != %d\n", so, s1); } + if (r) { ret++; printf("Error bool_2_cas no-op ret: %d\n", r); } + r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s1, s2); + if (so != s2) { + ret++; printf("Error bool_2_cas: %d != %d\n", so, s2); } + if (!r) { ret++; printf("Error bool_2_cas ret: %d\n", r); } +// int + r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i0, i2); // no-op + if (io != i1) { + ret++; printf("Error bool_4_cas no-op: %d != %d\n", io, i1); } + if (r) { ret++; printf("Error bool_4_cas no-op ret: %d\n", r); } + r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i1, i2); + if (io != i2) { + ret++; printf("Error bool_4_cas: %d != %d\n", io, i2); } + if (!r) { ret++; printf("Error bool_4_cas ret: %d\n", r); } +// long long + r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l0, l2); // no-op + if (lo != l1) { + ret++; printf("Error bool_8_cas no-op: %lld != %lld\n", lo, l1); } + if (r) { ret++; printf("Error bool_8_cas no-op ret: %d\n", r); } + r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l1, l2); + if (lo != l2) { + ret++; printf("Error bool_8_cas: %lld != %lld\n", lo, l2); } + if (!r) { ret++; printf("Error bool_8_cas ret: %d\n", r); } + +// #pragma omp atomic compare update capture +// { v = x; if (x == e) { x = d; } } +// char, co == c2 initially, co == c1 finally + cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c0, c1); // no-op + if (co != c2) { + ret++; printf("Error val_1_cas no-op: %d != %d\n", co, c2); } + if (cc != c2) { + ret++; printf("Error val_1_cas no-op ret: %d != %d\n", cc, c2); } + cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c2, c1); + if (co != c1) { + ret++; printf("Error val_1_cas: %d != %d\n", co, c1); } + if (cc != c2) { ret++; printf("Error val_1_cas ret: %d != %d\n", cc, c2); } +// short + sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s0, s1); // no-op + if (so != s2) { + ret++; printf("Error val_2_cas no-op: %d != %d\n", so, s2); } + if (sc != s2) { + ret++; printf("Error val_2_cas no-op ret: %d != %d\n", sc, s2); } + sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s2, s1); + if (so != s1) { + ret++; printf("Error val_2_cas: %d != %d\n", so, s1); } + if (sc != s2) { + ret++; printf("Error val_2_cas ret: %d != %d\n", sc, s2); } +// int + ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i0, i1); // no-op + if (io != i2) { + ret++; printf("Error val_4_cas no-op: %d != %d\n", io, i2); } + if (ic != i2) { + ret++; printf("Error val_4_cas no-op ret: %d != %d\n", ic, i2); } + ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i2, i1); + if (io != i1) { + ret++; printf("Error val_4_cas: %d != %d\n", io, i1); } + if (ic != i2) { + ret++; printf("Error val_4_cas ret: %d != %d\n", ic, i2); } +// long long + lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l0, l1); // no-op + if (lo != l2) { + ret++; printf("Error val_8_cas no-op: %lld != %lld\n", lo, l2); } + if (lc != l2) { + ret++; printf("Error val_8_cas no-op ret: %lld != %lld\n", lc, l2); } + lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l2, l1); + if (lo != l1) { + ret++; printf("Error val_8_cas: %lld != %lld\n", lo, l1); } + if (lc != l2) { + ret++; printf("Error val_8_cas ret: %lld != %lld\n", lc, l2); } + +// check in parallel + i0 = 1; + i1 = 0; + for (io = 0; io < 5; ++io) { + #pragma omp parallel num_threads(2) private(i2, ic, r) + { + if (omp_get_thread_num() == 0) { + // th0 waits for th1 to increment i1, then th0 increments i0 + #pragma omp atomic read + i2 = i1; + ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1); + while(ic != i2) { + #pragma omp atomic read + i2 = i1; + ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1); + } + } else { + // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed + r = 0; + while(!r) { + #pragma omp atomic read + i2 = i0; + r = __kmpc_atomic_bool_4_cas(NULL, 0, &i1, i2 - 1, i2); + } + } + } + } + if (i0 != 6 || i1 != 5) { + ret++; + printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5); + } + + if (ret == 0) + printf("passed\n"); + return ret; +} diff --git a/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c b/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c @@ -0,0 +1,219 @@ +// RUN: %libomp-compile-and-run + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef void* ident_t; +extern bool +__kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d, + char *pv); +extern bool +__kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d, + short *pv); +extern bool +__kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d, + int *pv); +extern bool +__kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, long long *x, long long e, + long long d, long long *pv); +extern char +__kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d, + char *pv); +extern short +__kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d, + short *pv); +extern int +__kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d, + int *pv); +extern long long +__kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, long long *x, long long e, + long long d, long long *pv); +#ifdef __cplusplus +} +#endif + +int main() { + int ret = 0; + bool r; + char c0 = 1; + char c1 = 2; + char c2 = 3; + char co = 2; + char cc = 0; + char cv = 0; + short s0 = 11; + short s1 = 12; + short s2 = 13; + short so = 12; + short sc = 0; + short sv = 0; + int i0 = 211; + int i1 = 212; + int i2 = 213; + int io = 212; + int ic = 0; + int iv = 0; + long long l0 = 3111; + long long l1 = 3112; + long long l2 = 3113; + long long lo = 3112; + long long lc = 0; + long long lv = 0; + +// initialize OpenMP runtime library + omp_set_dynamic(0); + +// #pragma omp atomic compare update capture +// { r = x == e; if(r) { x = d; } else { v = x; } } +// char, co == c1 initially, co == c2 finally + r = __kmpc_atomic_bool_1_cas_cpt(NULL, 0, &co, c0, c2, &cv); // no-op + if (co != c1) { + ret++; printf("Error bool_1_cas_cpt no-op: %d != %d\n", co, c1); } + if (cv != co) { + ret++; printf("Error bool_1_cas_cpt no-op cpt: %d != %d\n", cv, co); } + if (r) { ret++; printf("Error bool_1_cas_cpt no-op ret: %d\n", r); } + cv = 0; + r = __kmpc_atomic_bool_1_cas_cpt(NULL, 0, &co, c1, c2, &cv); + if (co != c2) { ret++; printf("Error bool_1_cas_cpt: %d != %d\n", co, c2); } + if (cv != 0) { ret++; printf("Error bool_1_cas_cpt cpt: %d != %d\n", cv, 0); } + if (!r) { ret++; printf("Error bool_1_cas_cpt ret: %d\n", r); } +// short + r = __kmpc_atomic_bool_2_cas_cpt(NULL, 0, &so, s0, s2, &sv); // no-op + if (so != s1) { + ret++; printf("Error bool_2_cas_cpt no-op: %d != %d\n", so, s1); } + if (sv != so) { + ret++; printf("Error bool_2_cas_cpt no-op cpt: %d != %d\n", sv, so); } + if (r) { ret++; printf("Error bool_2_cas_cpt no-op ret: %d\n", r); } + sv = 0; + r = __kmpc_atomic_bool_2_cas_cpt(NULL, 0, &so, s1, s2, &sv); + if (so != s2) { ret++; printf("Error bool_2_cas_cpt: %d != %d\n", so, s2); } + if (sv != 0) { ret++; printf("Error bool_2_cas_cpt cpt: %d != %d\n", sv, 0); } + if (!r) { ret++; printf("Error bool_2_cas_cpt ret: %d\n", r); } +// int + r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &io, i0, i2, &iv); // no-op + if (io != i1) { + ret++; printf("Error bool_4_cas_cpt no-op: %d != %d\n", io, i1); } + if (iv != io) { + ret++; printf("Error bool_4_cas_cpt no-op cpt: %d != %d\n", iv, io); } + if (r) { ret++; printf("Error bool_4_cas_cpt no-op ret: %d\n", r); } + iv = 0; + r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &io, i1, i2, &iv); + if (io != i2) { ret++; printf("Error bool_4_cas_cpt: %d != %d\n", io, i2); } + if (iv != 0) { ret++; printf("Error bool_4_cas_cpt cpt: %d != %d\n", iv, 0); } + if (!r) { ret++; printf("Error bool_4_cas_cpt ret: %d\n", r); } +// long long + r = __kmpc_atomic_bool_8_cas_cpt(NULL, 0, &lo, l0, l2, &lv); // no-op + if (lo != l1) { + ret++; printf("Error bool_8_cas_cpt no-op: %lld != %lld\n", lo, l1); } + if (lv != lo) { + ret++; printf("Error bool_8_cas_cpt no-op cpt: %lld != %lld\n", lv, lo); } + if (r) { ret++; printf("Error bool_8_cas_cpt no-op ret: %d\n", r); } + lv = 0; + r = __kmpc_atomic_bool_8_cas_cpt(NULL, 0, &lo, l1, l2, &lv); + if (lo != l2) { + ret++; printf("Error bool_8_cas_cpt: %lld != %lld\n", lo, l2); } + if (lv != 0) { // should not be assigned + ret++; printf("Error bool_8_cas_cpt cpt: %lld != %d\n", lv, 0); } + if (!r) { ret++; printf("Error bool_8_cas_cpt ret: %d\n", r); } + +// #pragma omp atomic compare update capture +// { if (x == e) { x = d; }; v = x; } +// char, co == c2 initially, co == c1 finally + cc = __kmpc_atomic_val_1_cas_cpt(NULL, 0, &co, c0, c1, &cv); // no-op + if (co != c2) { + ret++; printf("Error val_1_cas_cpt no-op: %d != %d\n", co, c2); } + if (cv != c2) { + ret++; printf("Error val_1_cas_cpt no-op cpt: %d != %d\n", cv, c2); } + if (cc != c2) { + ret++; printf("Error val_1_cas_cpt no-op ret: %d != %d\n", cc, c2); } + cc = __kmpc_atomic_val_1_cas_cpt(NULL, 0, &co, c2, c1, &cv); + if (co != c1) { ret++; printf("Error val_1_cas_cpt: %d != %d\n", co, c1); } + if (cv != c1) { ret++; printf("Error val_1_cas_cpt cpt: %d != %d\n", cv, c1); } + if (cc != c2) { ret++; printf("Error val_1_cas_cpt ret: %d != %d\n", cc, c2); } +// short + sc = __kmpc_atomic_val_2_cas_cpt(NULL, 0, &so, s0, s1, &sv); // no-op + if (so != s2) { + ret++; printf("Error val_2_cas_cpt no-op: %d != %d\n", so, s2); } + if (sv != s2) { + ret++; printf("Error val_2_cas_cpt no-op cpt: %d != %d\n", sv, s2); } + if (sc != s2) { + ret++; printf("Error val_2_cas_cpt no-op ret: %d != %d\n", sc, s2); } + sc = __kmpc_atomic_val_2_cas_cpt(NULL, 0, &so, s2, s1, &sv); + if (so != s1) { ret++; printf("Error val_2_cas_cpt: %d != %d\n", so, s1); } + if (sv != s1) { ret++; printf("Error val_2_cas_cpt cpt: %d != %d\n", sv, s1); } + if (sc != s2) { ret++; printf("Error val_2_cas_cpt ret: %d != %d\n", sc, s2); } +// int + ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &io, i0, i1, &iv); // no-op + if (io != i2) { + ret++; printf("Error val_4_cas_cpt no-op: %d != %d\n", io, i2); } + if (iv != i2) { + ret++; printf("Error val_4_cas_cpt no-op cpt: %d != %d\n", iv, i2); } + if (ic != i2) { + ret++; printf("Error val_4_cas_cpt no-op ret: %d != %d\n", ic, i2); } + ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &io, i2, i1, &iv); + if (io != i1) { ret++; printf("Error val_4_cas_cpt: %d != %d\n", io, i1); } + if (iv != i1) { ret++; printf("Error val_4_cas_cpt cpt: %d != %d\n", io, i1); } + if (ic != i2) { ret++; printf("Error val_4_cas_cpt ret: %d != %d\n", ic, i2); } +// long long + lc = __kmpc_atomic_val_8_cas_cpt(NULL, 0, &lo, l0, l1, &lv); // no-op + if (lo != l2) { + ret++; printf("Error val_8_cas_cpt no-op: %lld != %lld\n", lo, l2); } + if (lv != l2) { + ret++; printf("Error val_8_cas_cpt no-op cpt: %lld != %lld\n", lv, l2); } + if (lc != l2) { + ret++; printf("Error val_8_cas_cpt no-op ret: %lld != %lld\n", lc, l2); } + lc = __kmpc_atomic_val_8_cas_cpt(NULL, 0, &lo, l2, l1, &lv); + if (lo != l1) { ret++; printf("Error val_8_cas_cpt: %lld != %lld\n", lo, l1); } + if (lv != l1) { + ret++; printf("Error val_8_cas_cpt cpt: %lld != %lld\n", lv, l1); } + if (lc != l2) { + ret++; printf("Error val_8_cas_cpt ret: %lld != %lld\n", lc, l2); } + +// check in parallel + i0 = 1; + i1 = 0; + for (io = 0; io < 5; ++io) { + #pragma omp parallel num_threads(2) private(i2, ic, r, iv) + { + if (omp_get_thread_num() == 0) { + // th0 waits for th1 to increment i1, then th0 increments i0 + #pragma omp atomic read + i2 = i1; + ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &i0, i2, i2 + 1, &iv); + while(ic != i2) { + if (iv != ic) { + ret++; + printf("Error 1 in parallel cpt, %d != %d\n", iv, ic); + } + #pragma omp atomic read + i2 = i1; + ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &i0, i2, i2 + 1, &iv); + } + if (iv != i2 + 1) { + ret++; + printf("Error 2 in parallel cpt, %d != %d\n", iv, i2 + 1); + } + } else { + // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed + r = 0; + while(!r) { + #pragma omp atomic read + i2 = i0; + r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &i1, i2 - 1, i2, &iv); + } + } + } + } + if (i0 != 6 || i1 != 5) { + ret++; + printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5); + } + + if (ret == 0) + printf("passed\n"); + return ret; +} diff --git a/openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c b/openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/atomic/kmp_atomic_float10_max_min.c @@ -0,0 +1,155 @@ +// RUN: %libomp-compile -mlong-double-80 && %libomp-run +// UNSUPPORTED: gcc + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef void* ident_t; +extern void __kmpc_atomic_float10_max(ident_t *id_ref, int gtid, + long double *lhs, long double rhs); +extern void __kmpc_atomic_float10_min(ident_t *id_ref, int gtid, + long double *lhs, long double rhs); +extern long double __kmpc_atomic_float10_max_cpt(ident_t *id_ref, int gtid, + long double *lhs, + long double rhs, int flag); +extern long double __kmpc_atomic_float10_min_cpt(ident_t *id_ref, int gtid, + long double *lhs, + long double rhs, int flag); +#ifdef __cplusplus +} +#endif + +int main() { + int ret = 0; + long double s = 012.3456; // small + long double e = 123.4567; // middle + long double d = 234.5678; // big + long double x = 123.4567; // object + long double v = 0.; // captured value + +// initialize OpenMP runtime library + omp_set_num_threads(4); + +// max +// #pragma omp atomic compare update +// if (x < d) x = d; + __kmpc_atomic_float10_max(NULL, 0, &x, d); + if (x != d) { + ret++; + printf("Error max: %Lf != %Lf\n", x, d); + } + __kmpc_atomic_float10_max(NULL, 0, &x, s); // no-op + if (x != d) { + ret++; + printf("Error max: %Lf != %Lf\n", x, d); + } + +// min +// #pragma omp atomic compare update +// if (x > s) x = s; + __kmpc_atomic_float10_min(NULL, 0, &x, s); + if (x != s) { + ret++; + printf("Error min: %Lf != %Lf\n", x, s); + } + __kmpc_atomic_float10_min(NULL, 0, &x, e); // no-op + if (x != s) { + ret++; + printf("Error min: %Lf != %Lf\n", x, s); + } + +// max_cpt old +// #pragma omp atomic compare update capture +// { v = x; if (x < d) x = d; } + v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, d, 0); + if (x != d) { + ret++; + printf("Error max_cpt obj: %Lf != %Lf\n", x, d); + } + if (v != s) { + ret++; + printf("Error max_cpt cpt: %Lf != %Lf\n", v, s); + } + v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, e, 0); // no-op + if (x != d) { + ret++; + printf("Error max_cpt obj: %Lf != %Lf\n", x, d); + } + if (v != d) { + ret++; + printf("Error max_cpt cpt: %Lf != %Lf\n", v, d); + } + +// min_cpt old +// #pragma omp atomic compare update capture +// { v = x; if (x > d) x = d; } + v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, s, 0); + if (x != s) { + ret++; + printf("Error min_cpt obj: %Lf != %Lf\n", x, s); + } + if (v != d) { + ret++; + printf("Error min_cpt cpt: %Lf != %Lf\n", v, d); + } + v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, e, 0); // no-op + if (x != s) { + ret++; + printf("Error max_cpt obj: %Lf != %Lf\n", x, s); + } + if (v != s) { + ret++; + printf("Error max_cpt cpt: %Lf != %Lf\n", v, s); + } + +// max_cpt new +// #pragma omp atomic compare update capture +// { if (x < d) x = d; v = x; } + v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, d, 1); + if (x != d) { + ret++; + printf("Error max_cpt obj: %Lf != %Lf\n", x, d); + } + if (v != d) { + ret++; + printf("Error max_cpt cpt: %Lf != %Lf\n", v, d); + } + v = __kmpc_atomic_float10_max_cpt(NULL, 0, &x, e, 1); // no-op + if (x != d) { + ret++; + printf("Error max_cpt obj: %Lf != %Lf\n", x, d); + } + if (v != d) { + ret++; + printf("Error max_cpt cpt: %Lf != %Lf\n", v, d); + } + +// min_cpt new +// #pragma omp atomic compare update capture +// { if (x > d) x = d; v = x; } + v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, s, 1); + if (x != s) { + ret++; + printf("Error min_cpt obj: %Lf != %Lf\n", x, s); + } + if (v != s) { + ret++; + printf("Error min_cpt cpt: %Lf != %Lf\n", v, s); + } + v = __kmpc_atomic_float10_min_cpt(NULL, 0, &x, e, 1); // no-op + if (x != s) { + ret++; + printf("Error max_cpt obj: %Lf != %Lf\n", x, s); + } + if (v != s) { + ret++; + printf("Error max_cpt cpt: %Lf != %Lf\n", v, s); + } + + if (ret == 0) + printf("passed\n"); + return ret; +}