xref: /llvm-project/openmp/runtime/test/atomic/kmp_atomic_cas.c (revision 52f4922ebb7bfe5f9a6c32cf7d637b84e491526a)
1 // RUN: %libomp-compile-and-run
2 
3 #include <stdio.h>
4 #include <stdbool.h>
5 #include <omp.h>
6 
7 // Used to detect architecture
8 #include "../../src/kmp_platform.h"
9 
10 #ifdef  __cplusplus
11 extern "C" {
12 #endif
13 typedef void* ident_t;
14 extern bool
15 __kmpc_atomic_bool_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
16 extern bool
17 __kmpc_atomic_bool_2_cas(ident_t *loc, int gtid, short *x, short e, short d);
18 extern bool
19 __kmpc_atomic_bool_4_cas(ident_t *loc, int gtid, int *x, int e, int d);
20 extern bool
21 __kmpc_atomic_bool_8_cas(ident_t *loc, int gtid, long long *x, long long e,
22                          long long d);
23 extern char
24 __kmpc_atomic_val_1_cas(ident_t *loc, int gtid, char *x, char e, char d);
25 extern short
26 __kmpc_atomic_val_2_cas(ident_t *loc, int gtid, short *x, short e, short d);
27 extern int
28 __kmpc_atomic_val_4_cas(ident_t *loc, int gtid, int *x, int e, int d);
29 extern long long
30 __kmpc_atomic_val_8_cas(ident_t *loc, int gtid, long long *x, long long e,
31                         long long d);
32 #ifdef  __cplusplus
33 }
34 #endif
35 
main()36 int main() {
37   int ret = 0;
38 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
39   bool r;
40   char c0 = 1;
41   char c1 = 2;
42   char c2 = 3;
43   char co = 2;
44   char cc = 0;
45   short s0 = 11;
46   short s1 = 12;
47   short s2 = 13;
48   short so = 12;
49   short sc = 0;
50   int i0 = 211;
51   int i1 = 212;
52   int i2 = 213;
53   int io = 212;
54   int ic = 0;
55   long long l0 = 3111;
56   long long l1 = 3112;
57   long long l2 = 3113;
58   long long lo = 3112;
59   long long lc = 0;
60 
61 // initialize OpenMP runtime library
62   omp_set_dynamic(0);
63 
64 //  #pragma omp atomic compare update capture
65 //    { r = x == e; if(r) { x = d; } }
66 // char, co == c1 initially, co == c2 finally
67   r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c0, c2); // no-op
68   if (co != c1) {
69     ret++; printf("Error bool_1_cas no-op: %d != %d\n", co, c1); }
70   if (r) { ret++; printf("Error bool_1_cas no-op ret: %d\n", r); }
71   r = __kmpc_atomic_bool_1_cas(NULL, 0, &co, c1, c2);
72   if (co != c2) {
73     ret++; printf("Error bool_1_cas: %d != %d\n", co, c2); }
74   if (!r) { ret++; printf("Error bool_1_cas ret: %d\n", r); }
75 // short
76   r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s0, s2); // no-op
77   if (so != s1) {
78     ret++; printf("Error bool_2_cas no-op: %d != %d\n", so, s1); }
79   if (r) { ret++; printf("Error bool_2_cas no-op ret: %d\n", r); }
80   r = __kmpc_atomic_bool_2_cas(NULL, 0, &so, s1, s2);
81   if (so != s2) {
82     ret++; printf("Error bool_2_cas: %d != %d\n", so, s2); }
83   if (!r) { ret++; printf("Error bool_2_cas ret: %d\n", r); }
84 // int
85   r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i0, i2); // no-op
86   if (io != i1) {
87     ret++; printf("Error bool_4_cas no-op: %d != %d\n", io, i1); }
88   if (r) { ret++; printf("Error bool_4_cas no-op ret: %d\n", r); }
89   r = __kmpc_atomic_bool_4_cas(NULL, 0, &io, i1, i2);
90   if (io != i2) {
91     ret++; printf("Error bool_4_cas: %d != %d\n", io, i2); }
92   if (!r) { ret++; printf("Error bool_4_cas ret: %d\n", r); }
93 // long long
94   r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l0, l2); // no-op
95   if (lo != l1) {
96     ret++; printf("Error bool_8_cas no-op: %lld != %lld\n", lo, l1); }
97   if (r) { ret++; printf("Error bool_8_cas no-op ret: %d\n", r); }
98   r = __kmpc_atomic_bool_8_cas(NULL, 0, &lo, l1, l2);
99   if (lo != l2) {
100     ret++; printf("Error bool_8_cas: %lld != %lld\n", lo, l2); }
101   if (!r) { ret++; printf("Error bool_8_cas ret: %d\n", r); }
102 
103 //  #pragma omp atomic compare update capture
104 //    { v = x; if (x == e) { x = d; } }
105 // char, co == c2 initially, co == c1 finally
106   cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c0, c1); // no-op
107   if (co != c2) {
108     ret++; printf("Error val_1_cas no-op: %d != %d\n", co, c2); }
109   if (cc != c2) {
110     ret++; printf("Error val_1_cas no-op ret: %d != %d\n", cc, c2); }
111   cc = __kmpc_atomic_val_1_cas(NULL, 0, &co, c2, c1);
112   if (co != c1) {
113     ret++; printf("Error val_1_cas: %d != %d\n", co, c1); }
114   if (cc != c2) { ret++; printf("Error val_1_cas ret: %d != %d\n", cc, c2); }
115 // short
116   sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s0, s1); // no-op
117   if (so != s2) {
118     ret++; printf("Error val_2_cas no-op: %d != %d\n", so, s2); }
119   if (sc != s2) {
120     ret++; printf("Error val_2_cas no-op ret: %d != %d\n", sc, s2); }
121   sc = __kmpc_atomic_val_2_cas(NULL, 0, &so, s2, s1);
122   if (so != s1) {
123     ret++; printf("Error val_2_cas: %d != %d\n", so, s1); }
124   if (sc != s2) {
125     ret++; printf("Error val_2_cas ret: %d != %d\n", sc, s2); }
126 // int
127   ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i0, i1); // no-op
128   if (io != i2) {
129     ret++; printf("Error val_4_cas no-op: %d != %d\n", io, i2); }
130   if (ic != i2) {
131     ret++; printf("Error val_4_cas no-op ret: %d != %d\n", ic, i2); }
132   ic = __kmpc_atomic_val_4_cas(NULL, 0, &io, i2, i1);
133   if (io != i1) {
134     ret++; printf("Error val_4_cas: %d != %d\n", io, i1); }
135   if (ic != i2) {
136     ret++; printf("Error val_4_cas ret: %d != %d\n", ic, i2); }
137 // long long
138   lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l0, l1); // no-op
139   if (lo != l2) {
140     ret++; printf("Error val_8_cas no-op: %lld != %lld\n", lo, l2); }
141   if (lc != l2) {
142     ret++; printf("Error val_8_cas no-op ret: %lld != %lld\n", lc, l2); }
143   lc = __kmpc_atomic_val_8_cas(NULL, 0, &lo, l2, l1);
144   if (lo != l1) {
145     ret++; printf("Error val_8_cas: %lld != %lld\n", lo, l1); }
146   if (lc != l2) {
147     ret++; printf("Error val_8_cas ret: %lld != %lld\n", lc, l2); }
148 
149 // check in parallel
150   i0 = 1;
151   i1 = 0;
152   for (io = 0; io < 5; ++io) {
153     #pragma omp parallel num_threads(2) private(i2, ic, r)
154     {
155       if (omp_get_thread_num() == 0) {
156         // th0 waits for th1 to increment i1, then th0 increments i0
157         #pragma omp atomic read
158           i2 = i1;
159         ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1);
160         while(ic != i2) {
161           #pragma omp atomic read
162             i2 = i1;
163           ic = __kmpc_atomic_val_4_cas(NULL, 0, &i0, i2, i2 + 1);
164         }
165       } else {
166         // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed
167         r = 0;
168         while(!r) {
169           #pragma omp atomic read
170             i2 = i0;
171           r = __kmpc_atomic_bool_4_cas(NULL, 0, &i1, i2 - 1, i2);
172         }
173       }
174     }
175   }
176   if (i0 != 6 || i1 != 5) {
177     ret++;
178     printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5);
179   }
180 
181   if (ret == 0)
182     printf("passed\n");
183 #else
184   printf("Unsupported architecture, skipping test...\n");
185 #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
186   return ret;
187 }
188