xref: /llvm-project/openmp/runtime/test/atomic/kmp_atomic_cas_cpt.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_cpt(ident_t *loc, int gtid, char *x, char e, char d,
16                              char *pv);
17 extern bool
18 __kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d,
19                              short *pv);
20 extern bool
21 __kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d,
22                              int *pv);
23 extern bool
24 __kmpc_atomic_bool_8_cas_cpt(ident_t *loc, int gtid, long long *x, long long e,
25                              long long d, long long *pv);
26 extern char
27 __kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d,
28                             char *pv);
29 extern short
30 __kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d,
31                             short *pv);
32 extern int
33 __kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d,
34                             int *pv);
35 extern long long
36 __kmpc_atomic_val_8_cas_cpt(ident_t *loc, int gtid, long long *x, long long e,
37                             long long d, long long *pv);
38 #ifdef  __cplusplus
39 }
40 #endif
41 
main()42 int main() {
43   int ret = 0;
44 #if KMP_ARCH_X86 || KMP_ARCH_X86_64
45   bool r;
46   char c0 = 1;
47   char c1 = 2;
48   char c2 = 3;
49   char co = 2;
50   char cc = 0;
51   char cv = 0;
52   short s0 = 11;
53   short s1 = 12;
54   short s2 = 13;
55   short so = 12;
56   short sc = 0;
57   short sv = 0;
58   int i0 = 211;
59   int i1 = 212;
60   int i2 = 213;
61   int io = 212;
62   int ic = 0;
63   int iv = 0;
64   long long l0 = 3111;
65   long long l1 = 3112;
66   long long l2 = 3113;
67   long long lo = 3112;
68   long long lc = 0;
69   long long lv = 0;
70 
71 // initialize OpenMP runtime library
72   omp_set_dynamic(0);
73 
74 //  #pragma omp atomic compare update capture
75 //    { r = x == e; if(r) { x = d; } else { v = x; } }
76 // char, co == c1 initially, co == c2 finally
77   r = __kmpc_atomic_bool_1_cas_cpt(NULL, 0, &co, c0, c2, &cv); // no-op
78   if (co != c1) {
79     ret++; printf("Error bool_1_cas_cpt no-op: %d != %d\n", co, c1); }
80   if (cv != co) {
81     ret++; printf("Error bool_1_cas_cpt no-op cpt: %d != %d\n", cv, co); }
82   if (r) { ret++; printf("Error bool_1_cas_cpt no-op ret: %d\n", r); }
83   cv = 0;
84   r = __kmpc_atomic_bool_1_cas_cpt(NULL, 0, &co, c1, c2, &cv);
85   if (co != c2) { ret++; printf("Error bool_1_cas_cpt: %d != %d\n", co, c2); }
86   if (cv != 0) { ret++; printf("Error bool_1_cas_cpt cpt: %d != %d\n", cv, 0); }
87   if (!r) { ret++; printf("Error bool_1_cas_cpt ret: %d\n", r); }
88 // short
89   r = __kmpc_atomic_bool_2_cas_cpt(NULL, 0, &so, s0, s2, &sv); // no-op
90   if (so != s1) {
91     ret++; printf("Error bool_2_cas_cpt no-op: %d != %d\n", so, s1); }
92   if (sv != so) {
93     ret++; printf("Error bool_2_cas_cpt no-op cpt: %d != %d\n", sv, so); }
94   if (r) { ret++; printf("Error bool_2_cas_cpt no-op ret: %d\n", r); }
95   sv = 0;
96   r = __kmpc_atomic_bool_2_cas_cpt(NULL, 0, &so, s1, s2, &sv);
97   if (so != s2) { ret++; printf("Error bool_2_cas_cpt: %d != %d\n", so, s2); }
98   if (sv != 0) { ret++; printf("Error bool_2_cas_cpt cpt: %d != %d\n", sv, 0); }
99   if (!r) { ret++; printf("Error bool_2_cas_cpt ret: %d\n", r); }
100 // int
101   r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &io, i0, i2, &iv); // no-op
102   if (io != i1) {
103     ret++; printf("Error bool_4_cas_cpt no-op: %d != %d\n", io, i1); }
104   if (iv != io) {
105     ret++; printf("Error bool_4_cas_cpt no-op cpt: %d != %d\n", iv, io); }
106   if (r) { ret++; printf("Error bool_4_cas_cpt no-op ret: %d\n", r); }
107   iv = 0;
108   r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &io, i1, i2, &iv);
109   if (io != i2) { ret++; printf("Error bool_4_cas_cpt: %d != %d\n", io, i2); }
110   if (iv != 0) { ret++; printf("Error bool_4_cas_cpt cpt: %d != %d\n", iv, 0); }
111   if (!r) { ret++; printf("Error bool_4_cas_cpt ret: %d\n", r); }
112 // long long
113   r = __kmpc_atomic_bool_8_cas_cpt(NULL, 0, &lo, l0, l2, &lv); // no-op
114   if (lo != l1) {
115     ret++; printf("Error bool_8_cas_cpt no-op: %lld != %lld\n", lo, l1); }
116   if (lv != lo) {
117     ret++; printf("Error bool_8_cas_cpt no-op cpt: %lld != %lld\n", lv, lo); }
118   if (r) { ret++; printf("Error bool_8_cas_cpt no-op ret: %d\n", r); }
119   lv = 0;
120   r = __kmpc_atomic_bool_8_cas_cpt(NULL, 0, &lo, l1, l2, &lv);
121   if (lo != l2) {
122     ret++; printf("Error bool_8_cas_cpt: %lld != %lld\n", lo, l2); }
123   if (lv != 0) { // should not be assigned
124     ret++; printf("Error bool_8_cas_cpt cpt: %lld != %d\n", lv, 0); }
125   if (!r) { ret++; printf("Error bool_8_cas_cpt ret: %d\n", r); }
126 
127 //  #pragma omp atomic compare update capture
128 //    { if (x == e) { x = d; }; v = x; }
129 // char, co == c2 initially, co == c1 finally
130   cc = __kmpc_atomic_val_1_cas_cpt(NULL, 0, &co, c0, c1, &cv); // no-op
131   if (co != c2) {
132     ret++; printf("Error val_1_cas_cpt no-op: %d != %d\n", co, c2); }
133   if (cv != c2) {
134     ret++; printf("Error val_1_cas_cpt no-op cpt: %d != %d\n", cv, c2); }
135   if (cc != c2) {
136     ret++; printf("Error val_1_cas_cpt no-op ret: %d != %d\n", cc, c2); }
137   cc = __kmpc_atomic_val_1_cas_cpt(NULL, 0, &co, c2, c1, &cv);
138   if (co != c1) { ret++; printf("Error val_1_cas_cpt: %d != %d\n", co, c1); }
139   if (cv != c1) { ret++; printf("Error val_1_cas_cpt cpt: %d != %d\n", cv, c1); }
140   if (cc != c2) { ret++; printf("Error val_1_cas_cpt ret: %d != %d\n", cc, c2); }
141 // short
142   sc = __kmpc_atomic_val_2_cas_cpt(NULL, 0, &so, s0, s1, &sv); // no-op
143   if (so != s2) {
144     ret++; printf("Error val_2_cas_cpt no-op: %d != %d\n", so, s2); }
145   if (sv != s2) {
146     ret++; printf("Error val_2_cas_cpt no-op cpt: %d != %d\n", sv, s2); }
147   if (sc != s2) {
148     ret++; printf("Error val_2_cas_cpt no-op ret: %d != %d\n", sc, s2); }
149   sc = __kmpc_atomic_val_2_cas_cpt(NULL, 0, &so, s2, s1, &sv);
150   if (so != s1) { ret++; printf("Error val_2_cas_cpt: %d != %d\n", so, s1); }
151   if (sv != s1) { ret++; printf("Error val_2_cas_cpt cpt: %d != %d\n", sv, s1); }
152   if (sc != s2) { ret++; printf("Error val_2_cas_cpt ret: %d != %d\n", sc, s2); }
153 // int
154   ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &io, i0, i1, &iv); // no-op
155   if (io != i2) {
156     ret++; printf("Error val_4_cas_cpt no-op: %d != %d\n", io, i2); }
157   if (iv != i2) {
158     ret++; printf("Error val_4_cas_cpt no-op cpt: %d != %d\n", iv, i2); }
159   if (ic != i2) {
160     ret++; printf("Error val_4_cas_cpt no-op ret: %d != %d\n", ic, i2); }
161   ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &io, i2, i1, &iv);
162   if (io != i1) { ret++; printf("Error val_4_cas_cpt: %d != %d\n", io, i1); }
163   if (iv != i1) { ret++; printf("Error val_4_cas_cpt cpt: %d != %d\n", io, i1); }
164   if (ic != i2) { ret++; printf("Error val_4_cas_cpt ret: %d != %d\n", ic, i2); }
165 // long long
166   lc = __kmpc_atomic_val_8_cas_cpt(NULL, 0, &lo, l0, l1, &lv); // no-op
167   if (lo != l2) {
168     ret++; printf("Error val_8_cas_cpt no-op: %lld != %lld\n", lo, l2); }
169   if (lv != l2) {
170     ret++; printf("Error val_8_cas_cpt no-op cpt: %lld != %lld\n", lv, l2); }
171   if (lc != l2) {
172     ret++; printf("Error val_8_cas_cpt no-op ret: %lld != %lld\n", lc, l2); }
173   lc = __kmpc_atomic_val_8_cas_cpt(NULL, 0, &lo, l2, l1, &lv);
174   if (lo != l1) { ret++; printf("Error val_8_cas_cpt: %lld != %lld\n", lo, l1); }
175   if (lv != l1) {
176     ret++; printf("Error val_8_cas_cpt cpt: %lld != %lld\n", lv, l1); }
177   if (lc != l2) {
178     ret++; printf("Error val_8_cas_cpt ret: %lld != %lld\n", lc, l2); }
179 
180 // check in parallel
181   i0 = 1;
182   i1 = 0;
183   for (io = 0; io < 5; ++io) {
184     #pragma omp parallel num_threads(2) private(i2, ic, r, iv)
185     {
186       if (omp_get_thread_num() == 0) {
187         // th0 waits for th1 to increment i1, then th0 increments i0
188         #pragma omp atomic read
189           i2 = i1;
190         ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &i0, i2, i2 + 1, &iv);
191         while(ic != i2) {
192           if (iv != ic) {
193             ret++;
194             printf("Error 1 in parallel cpt, %d != %d\n", iv, ic);
195           }
196           #pragma omp atomic read
197             i2 = i1;
198           ic = __kmpc_atomic_val_4_cas_cpt(NULL, 0, &i0, i2, i2 + 1, &iv);
199         }
200         if (iv != i2 + 1) {
201           ret++;
202           printf("Error 2 in parallel cpt, %d != %d\n", iv, i2 + 1);
203         }
204       } else {
205         // th1 increments i1 if it is equal to i0 - 1, letting th0 to proceed
206         r = 0;
207         while(!r) {
208           #pragma omp atomic read
209             i2 = i0;
210           r = __kmpc_atomic_bool_4_cas_cpt(NULL, 0, &i1, i2 - 1, i2, &iv);
211         }
212       }
213     }
214   }
215   if (i0 != 6 || i1 != 5) {
216     ret++;
217     printf("Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5);
218   }
219 
220   if (ret == 0)
221     printf("passed\n");
222 #else
223   printf("Unsupported architecture, skipping test...\n");
224 #endif // KMP_ARCH_X86 || KMP_ARCH_X86_64
225   return ret;
226 }
227