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
11extern "C" {
12#endif
13typedef void* ident_t;
14extern bool
15__kmpc_atomic_bool_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d,
16 char *pv);
17extern bool
18__kmpc_atomic_bool_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d,
19 short *pv);
20extern bool
21__kmpc_atomic_bool_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d,
22 int *pv);
23extern 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);
26extern char
27__kmpc_atomic_val_1_cas_cpt(ident_t *loc, int gtid, char *x, char e, char d,
28 char *pv);
29extern short
30__kmpc_atomic_val_2_cas_cpt(ident_t *loc, int gtid, short *x, short e, short d,
31 short *pv);
32extern int
33__kmpc_atomic_val_4_cas_cpt(ident_t *loc, int gtid, int *x, int e, int d,
34 int *pv);
35extern 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
42int 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, gtid: 0, x: &co, e: c0, d: c2, pv: &cv); // no-op
78 if (co != c1) {
79 ret++; printf(format: "Error bool_1_cas_cpt no-op: %d != %d\n", co, c1); }
80 if (cv != co) {
81 ret++; printf(format: "Error bool_1_cas_cpt no-op cpt: %d != %d\n", cv, co); }
82 if (r) { ret++; printf(format: "Error bool_1_cas_cpt no-op ret: %d\n", r); }
83 cv = 0;
84 r = __kmpc_atomic_bool_1_cas_cpt(NULL, gtid: 0, x: &co, e: c1, d: c2, pv: &cv);
85 if (co != c2) { ret++; printf(format: "Error bool_1_cas_cpt: %d != %d\n", co, c2); }
86 if (cv != 0) { ret++; printf(format: "Error bool_1_cas_cpt cpt: %d != %d\n", cv, 0); }
87 if (!r) { ret++; printf(format: "Error bool_1_cas_cpt ret: %d\n", r); }
88// short
89 r = __kmpc_atomic_bool_2_cas_cpt(NULL, gtid: 0, x: &so, e: s0, d: s2, pv: &sv); // no-op
90 if (so != s1) {
91 ret++; printf(format: "Error bool_2_cas_cpt no-op: %d != %d\n", so, s1); }
92 if (sv != so) {
93 ret++; printf(format: "Error bool_2_cas_cpt no-op cpt: %d != %d\n", sv, so); }
94 if (r) { ret++; printf(format: "Error bool_2_cas_cpt no-op ret: %d\n", r); }
95 sv = 0;
96 r = __kmpc_atomic_bool_2_cas_cpt(NULL, gtid: 0, x: &so, e: s1, d: s2, pv: &sv);
97 if (so != s2) { ret++; printf(format: "Error bool_2_cas_cpt: %d != %d\n", so, s2); }
98 if (sv != 0) { ret++; printf(format: "Error bool_2_cas_cpt cpt: %d != %d\n", sv, 0); }
99 if (!r) { ret++; printf(format: "Error bool_2_cas_cpt ret: %d\n", r); }
100// int
101 r = __kmpc_atomic_bool_4_cas_cpt(NULL, gtid: 0, x: &io, e: i0, d: i2, pv: &iv); // no-op
102 if (io != i1) {
103 ret++; printf(format: "Error bool_4_cas_cpt no-op: %d != %d\n", io, i1); }
104 if (iv != io) {
105 ret++; printf(format: "Error bool_4_cas_cpt no-op cpt: %d != %d\n", iv, io); }
106 if (r) { ret++; printf(format: "Error bool_4_cas_cpt no-op ret: %d\n", r); }
107 iv = 0;
108 r = __kmpc_atomic_bool_4_cas_cpt(NULL, gtid: 0, x: &io, e: i1, d: i2, pv: &iv);
109 if (io != i2) { ret++; printf(format: "Error bool_4_cas_cpt: %d != %d\n", io, i2); }
110 if (iv != 0) { ret++; printf(format: "Error bool_4_cas_cpt cpt: %d != %d\n", iv, 0); }
111 if (!r) { ret++; printf(format: "Error bool_4_cas_cpt ret: %d\n", r); }
112// long long
113 r = __kmpc_atomic_bool_8_cas_cpt(NULL, gtid: 0, x: &lo, e: l0, d: l2, pv: &lv); // no-op
114 if (lo != l1) {
115 ret++; printf(format: "Error bool_8_cas_cpt no-op: %lld != %lld\n", lo, l1); }
116 if (lv != lo) {
117 ret++; printf(format: "Error bool_8_cas_cpt no-op cpt: %lld != %lld\n", lv, lo); }
118 if (r) { ret++; printf(format: "Error bool_8_cas_cpt no-op ret: %d\n", r); }
119 lv = 0;
120 r = __kmpc_atomic_bool_8_cas_cpt(NULL, gtid: 0, x: &lo, e: l1, d: l2, pv: &lv);
121 if (lo != l2) {
122 ret++; printf(format: "Error bool_8_cas_cpt: %lld != %lld\n", lo, l2); }
123 if (lv != 0) { // should not be assigned
124 ret++; printf(format: "Error bool_8_cas_cpt cpt: %lld != %d\n", lv, 0); }
125 if (!r) { ret++; printf(format: "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, gtid: 0, x: &co, e: c0, d: c1, pv: &cv); // no-op
131 if (co != c2) {
132 ret++; printf(format: "Error val_1_cas_cpt no-op: %d != %d\n", co, c2); }
133 if (cv != c2) {
134 ret++; printf(format: "Error val_1_cas_cpt no-op cpt: %d != %d\n", cv, c2); }
135 if (cc != c2) {
136 ret++; printf(format: "Error val_1_cas_cpt no-op ret: %d != %d\n", cc, c2); }
137 cc = __kmpc_atomic_val_1_cas_cpt(NULL, gtid: 0, x: &co, e: c2, d: c1, pv: &cv);
138 if (co != c1) { ret++; printf(format: "Error val_1_cas_cpt: %d != %d\n", co, c1); }
139 if (cv != c1) { ret++; printf(format: "Error val_1_cas_cpt cpt: %d != %d\n", cv, c1); }
140 if (cc != c2) { ret++; printf(format: "Error val_1_cas_cpt ret: %d != %d\n", cc, c2); }
141// short
142 sc = __kmpc_atomic_val_2_cas_cpt(NULL, gtid: 0, x: &so, e: s0, d: s1, pv: &sv); // no-op
143 if (so != s2) {
144 ret++; printf(format: "Error val_2_cas_cpt no-op: %d != %d\n", so, s2); }
145 if (sv != s2) {
146 ret++; printf(format: "Error val_2_cas_cpt no-op cpt: %d != %d\n", sv, s2); }
147 if (sc != s2) {
148 ret++; printf(format: "Error val_2_cas_cpt no-op ret: %d != %d\n", sc, s2); }
149 sc = __kmpc_atomic_val_2_cas_cpt(NULL, gtid: 0, x: &so, e: s2, d: s1, pv: &sv);
150 if (so != s1) { ret++; printf(format: "Error val_2_cas_cpt: %d != %d\n", so, s1); }
151 if (sv != s1) { ret++; printf(format: "Error val_2_cas_cpt cpt: %d != %d\n", sv, s1); }
152 if (sc != s2) { ret++; printf(format: "Error val_2_cas_cpt ret: %d != %d\n", sc, s2); }
153// int
154 ic = __kmpc_atomic_val_4_cas_cpt(NULL, gtid: 0, x: &io, e: i0, d: i1, pv: &iv); // no-op
155 if (io != i2) {
156 ret++; printf(format: "Error val_4_cas_cpt no-op: %d != %d\n", io, i2); }
157 if (iv != i2) {
158 ret++; printf(format: "Error val_4_cas_cpt no-op cpt: %d != %d\n", iv, i2); }
159 if (ic != i2) {
160 ret++; printf(format: "Error val_4_cas_cpt no-op ret: %d != %d\n", ic, i2); }
161 ic = __kmpc_atomic_val_4_cas_cpt(NULL, gtid: 0, x: &io, e: i2, d: i1, pv: &iv);
162 if (io != i1) { ret++; printf(format: "Error val_4_cas_cpt: %d != %d\n", io, i1); }
163 if (iv != i1) { ret++; printf(format: "Error val_4_cas_cpt cpt: %d != %d\n", io, i1); }
164 if (ic != i2) { ret++; printf(format: "Error val_4_cas_cpt ret: %d != %d\n", ic, i2); }
165// long long
166 lc = __kmpc_atomic_val_8_cas_cpt(NULL, gtid: 0, x: &lo, e: l0, d: l1, pv: &lv); // no-op
167 if (lo != l2) {
168 ret++; printf(format: "Error val_8_cas_cpt no-op: %lld != %lld\n", lo, l2); }
169 if (lv != l2) {
170 ret++; printf(format: "Error val_8_cas_cpt no-op cpt: %lld != %lld\n", lv, l2); }
171 if (lc != l2) {
172 ret++; printf(format: "Error val_8_cas_cpt no-op ret: %lld != %lld\n", lc, l2); }
173 lc = __kmpc_atomic_val_8_cas_cpt(NULL, gtid: 0, x: &lo, e: l2, d: l1, pv: &lv);
174 if (lo != l1) { ret++; printf(format: "Error val_8_cas_cpt: %lld != %lld\n", lo, l1); }
175 if (lv != l1) {
176 ret++; printf(format: "Error val_8_cas_cpt cpt: %lld != %lld\n", lv, l1); }
177 if (lc != l2) {
178 ret++; printf(format: "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, gtid: 0, x: &i0, e: i2, d: i2 + 1, pv: &iv);
191 while(ic != i2) {
192 if (iv != ic) {
193 ret++;
194 printf(format: "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, gtid: 0, x: &i0, e: i2, d: i2 + 1, pv: &iv);
199 }
200 if (iv != i2 + 1) {
201 ret++;
202 printf(format: "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, gtid: 0, x: &i1, e: i2 - 1, d: i2, pv: &iv);
211 }
212 }
213 }
214 }
215 if (i0 != 6 || i1 != 5) {
216 ret++;
217 printf(format: "Error in parallel, %d != %d or %d != %d\n", i0, 6, i1, 5);
218 }
219
220 if (ret == 0)
221 printf(format: "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

source code of openmp/runtime/test/atomic/kmp_atomic_cas_cpt.c