1*6ef16f26SJoachim Jenke // RUN: %libomp-compile-and-run | FileCheck %s
2*6ef16f26SJoachim Jenke // REQUIRES: ompt
3*6ef16f26SJoachim Jenke
4*6ef16f26SJoachim Jenke // RUN: %libomp-compile-and-run
5*6ef16f26SJoachim Jenke // The runtime currently does not get dependency information from GCC.
6*6ef16f26SJoachim Jenke // UNSUPPORTED: gcc
7*6ef16f26SJoachim Jenke
8*6ef16f26SJoachim Jenke // Tests OMP 5.x task dependence "omp_all_memory",
9*6ef16f26SJoachim Jenke // emulates compiler codegen versions for new dep kind
10*6ef16f26SJoachim Jenke //
11*6ef16f26SJoachim Jenke // Task tree created:
12*6ef16f26SJoachim Jenke // task0 - task1 (in: i1, i2)
13*6ef16f26SJoachim Jenke // \
14*6ef16f26SJoachim Jenke // task2 (inoutset: i2), (in: i1)
15*6ef16f26SJoachim Jenke // /
16*6ef16f26SJoachim Jenke // task3 (omp_all_memory) via flag=0x80
17*6ef16f26SJoachim Jenke // /
18*6ef16f26SJoachim Jenke // task4 - task5 (in: i1, i2)
19*6ef16f26SJoachim Jenke // /
20*6ef16f26SJoachim Jenke // task6 (omp_all_memory) via addr=-1
21*6ef16f26SJoachim Jenke // /
22*6ef16f26SJoachim Jenke // task7 (omp_all_memory) via flag=0x80
23*6ef16f26SJoachim Jenke // /
24*6ef16f26SJoachim Jenke // task8 (in: i3)
25*6ef16f26SJoachim Jenke //
26*6ef16f26SJoachim Jenke
27*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
28*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
29*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
30*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
31*6ef16f26SJoachim Jenke
32*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
33*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
34*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
35*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
36*6ef16f26SJoachim Jenke
37*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
38*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
39*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_inoutset
40*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
41*6ef16f26SJoachim Jenke
42*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
43*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
44*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_out_all_memory
45*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
46*6ef16f26SJoachim Jenke
47*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
48*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
49*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
50*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
51*6ef16f26SJoachim Jenke
52*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
53*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
54*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
55*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
56*6ef16f26SJoachim Jenke
57*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
58*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_out_all_memory
59*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=1
60*6ef16f26SJoachim Jenke
61*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
62*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_out_all_memory
63*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_mutexinoutset
64*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=2
65*6ef16f26SJoachim Jenke
66*6ef16f26SJoachim Jenke // CHECK: ompt_event_dependences:
67*6ef16f26SJoachim Jenke // CHECK-SAME: ompt_dependence_type_in
68*6ef16f26SJoachim Jenke // CHECK-SAME: ndeps=1
69*6ef16f26SJoachim Jenke
70*6ef16f26SJoachim Jenke #include "callback.h"
71*6ef16f26SJoachim Jenke #include <stdio.h>
72*6ef16f26SJoachim Jenke #include <omp.h>
73*6ef16f26SJoachim Jenke
74*6ef16f26SJoachim Jenke #ifdef _WIN32
75*6ef16f26SJoachim Jenke #include <windows.h>
76*6ef16f26SJoachim Jenke #define mysleep(n) Sleep(n)
77*6ef16f26SJoachim Jenke #else
78*6ef16f26SJoachim Jenke #include <unistd.h>
79*6ef16f26SJoachim Jenke #define mysleep(n) usleep((n)*1000)
80*6ef16f26SJoachim Jenke #endif
81*6ef16f26SJoachim Jenke
82*6ef16f26SJoachim Jenke // to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)
83*6ef16f26SJoachim Jenke static int checker = 0;
84*6ef16f26SJoachim Jenke static int err = 0;
85*6ef16f26SJoachim Jenke #ifndef DELAY
86*6ef16f26SJoachim Jenke #define DELAY 100
87*6ef16f26SJoachim Jenke #endif
88*6ef16f26SJoachim Jenke
89*6ef16f26SJoachim Jenke // ---------------------------------------------------------------------------
90*6ef16f26SJoachim Jenke // internal data to emulate compiler codegen
91*6ef16f26SJoachim Jenke typedef struct DEP {
92*6ef16f26SJoachim Jenke size_t addr;
93*6ef16f26SJoachim Jenke size_t len;
94*6ef16f26SJoachim Jenke unsigned char flags;
95*6ef16f26SJoachim Jenke } dep;
96*6ef16f26SJoachim Jenke #define DEP_ALL_MEM 0x80
97*6ef16f26SJoachim Jenke typedef struct task {
98*6ef16f26SJoachim Jenke void **shareds;
99*6ef16f26SJoachim Jenke void *entry;
100*6ef16f26SJoachim Jenke int part_id;
101*6ef16f26SJoachim Jenke void *destr_thunk;
102*6ef16f26SJoachim Jenke int priority;
103*6ef16f26SJoachim Jenke long long device_id;
104*6ef16f26SJoachim Jenke int f_priv;
105*6ef16f26SJoachim Jenke } task_t;
106*6ef16f26SJoachim Jenke #define TIED 1
107*6ef16f26SJoachim Jenke typedef int (*entry_t)(int, task_t *);
108*6ef16f26SJoachim Jenke typedef struct ID {
109*6ef16f26SJoachim Jenke int reserved_1;
110*6ef16f26SJoachim Jenke int flags;
111*6ef16f26SJoachim Jenke int reserved_2;
112*6ef16f26SJoachim Jenke int reserved_3;
113*6ef16f26SJoachim Jenke char *psource;
114*6ef16f26SJoachim Jenke } id;
115*6ef16f26SJoachim Jenke // thunk routine for tasks with ALL dependency
thunk_m(int gtid,task_t * ptask)116*6ef16f26SJoachim Jenke int thunk_m(int gtid, task_t *ptask) {
117*6ef16f26SJoachim Jenke int lcheck, th;
118*6ef16f26SJoachim Jenke #pragma omp atomic capture
119*6ef16f26SJoachim Jenke lcheck = ++checker;
120*6ef16f26SJoachim Jenke th = omp_get_thread_num();
121*6ef16f26SJoachim Jenke printf("task m_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);
122*6ef16f26SJoachim Jenke if (lcheck != 1) { // no more than 1 task at a time
123*6ef16f26SJoachim Jenke err++;
124*6ef16f26SJoachim Jenke printf("Error m1, checker %d != 1\n", lcheck);
125*6ef16f26SJoachim Jenke }
126*6ef16f26SJoachim Jenke mysleep(DELAY);
127*6ef16f26SJoachim Jenke #pragma omp atomic read
128*6ef16f26SJoachim Jenke lcheck = checker; // must still be equal to 1
129*6ef16f26SJoachim Jenke if (lcheck != 1) {
130*6ef16f26SJoachim Jenke err++;
131*6ef16f26SJoachim Jenke printf("Error m2, checker %d != 1\n", lcheck);
132*6ef16f26SJoachim Jenke }
133*6ef16f26SJoachim Jenke #pragma omp atomic
134*6ef16f26SJoachim Jenke --checker;
135*6ef16f26SJoachim Jenke return 0;
136*6ef16f26SJoachim Jenke }
137*6ef16f26SJoachim Jenke // thunk routine for tasks with inoutset dependency
thunk_s(int gtid,task_t * ptask)138*6ef16f26SJoachim Jenke int thunk_s(int gtid, task_t *ptask) {
139*6ef16f26SJoachim Jenke int lcheck, th;
140*6ef16f26SJoachim Jenke #pragma omp atomic capture
141*6ef16f26SJoachim Jenke lcheck = ++checker; // 1
142*6ef16f26SJoachim Jenke th = omp_get_thread_num();
143*6ef16f26SJoachim Jenke printf("task 2_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);
144*6ef16f26SJoachim Jenke if (lcheck != 1) { // no more than 1 task at a time
145*6ef16f26SJoachim Jenke err++;
146*6ef16f26SJoachim Jenke printf("Error s1, checker %d != 1\n", lcheck);
147*6ef16f26SJoachim Jenke }
148*6ef16f26SJoachim Jenke mysleep(DELAY);
149*6ef16f26SJoachim Jenke #pragma omp atomic read
150*6ef16f26SJoachim Jenke lcheck = checker; // must still be equal to 1
151*6ef16f26SJoachim Jenke if (lcheck != 1) {
152*6ef16f26SJoachim Jenke err++;
153*6ef16f26SJoachim Jenke printf("Error s2, checker %d != 1\n", lcheck);
154*6ef16f26SJoachim Jenke }
155*6ef16f26SJoachim Jenke #pragma omp atomic
156*6ef16f26SJoachim Jenke --checker;
157*6ef16f26SJoachim Jenke return 0;
158*6ef16f26SJoachim Jenke }
159*6ef16f26SJoachim Jenke
160*6ef16f26SJoachim Jenke #ifdef __cplusplus
161*6ef16f26SJoachim Jenke extern "C" {
162*6ef16f26SJoachim Jenke #endif
163*6ef16f26SJoachim Jenke int __kmpc_global_thread_num(id *);
164*6ef16f26SJoachim Jenke task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,
165*6ef16f26SJoachim Jenke size_t shar, entry_t rtn);
166*6ef16f26SJoachim Jenke int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,
167*6ef16f26SJoachim Jenke dep *dep_lst, int nd_noalias, dep *noalias_lst);
168*6ef16f26SJoachim Jenke static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};
169*6ef16f26SJoachim Jenke #ifdef __cplusplus
170*6ef16f26SJoachim Jenke } // extern "C"
171*6ef16f26SJoachim Jenke #endif
172*6ef16f26SJoachim Jenke // End of internal data
173*6ef16f26SJoachim Jenke // ---------------------------------------------------------------------------
174*6ef16f26SJoachim Jenke
main()175*6ef16f26SJoachim Jenke int main() {
176*6ef16f26SJoachim Jenke int i1, i2, i3;
177*6ef16f26SJoachim Jenke omp_set_num_threads(8);
178*6ef16f26SJoachim Jenke omp_set_dynamic(0);
179*6ef16f26SJoachim Jenke #pragma omp parallel
180*6ef16f26SJoachim Jenke {
181*6ef16f26SJoachim Jenke #pragma omp single nowait
182*6ef16f26SJoachim Jenke {
183*6ef16f26SJoachim Jenke dep sdep[2];
184*6ef16f26SJoachim Jenke task_t *ptr;
185*6ef16f26SJoachim Jenke int gtid = __kmpc_global_thread_num(&loc);
186*6ef16f26SJoachim Jenke int t = omp_get_thread_num();
187*6ef16f26SJoachim Jenke #pragma omp task depend(in : i1, i2)
188*6ef16f26SJoachim Jenke { // task 0
189*6ef16f26SJoachim Jenke int lcheck, th;
190*6ef16f26SJoachim Jenke #pragma omp atomic capture
191*6ef16f26SJoachim Jenke lcheck = ++checker; // 1 or 2
192*6ef16f26SJoachim Jenke th = omp_get_thread_num();
193*6ef16f26SJoachim Jenke printf("task 0_%d, th %d, checker %d\n", t, th, lcheck);
194*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
195*6ef16f26SJoachim Jenke err++; // no more than 2 tasks concurrently
196*6ef16f26SJoachim Jenke printf("Error1, checker %d, not 1 or 2\n", lcheck);
197*6ef16f26SJoachim Jenke }
198*6ef16f26SJoachim Jenke mysleep(DELAY);
199*6ef16f26SJoachim Jenke #pragma omp atomic read
200*6ef16f26SJoachim Jenke lcheck = checker; // 1 or 2
201*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
202*6ef16f26SJoachim Jenke #pragma omp atomic
203*6ef16f26SJoachim Jenke err++;
204*6ef16f26SJoachim Jenke printf("Error2, checker %d, not 1 or 2\n", lcheck);
205*6ef16f26SJoachim Jenke }
206*6ef16f26SJoachim Jenke #pragma omp atomic
207*6ef16f26SJoachim Jenke --checker;
208*6ef16f26SJoachim Jenke }
209*6ef16f26SJoachim Jenke #pragma omp task depend(in : i1, i2)
210*6ef16f26SJoachim Jenke { // task 1
211*6ef16f26SJoachim Jenke int lcheck, th;
212*6ef16f26SJoachim Jenke #pragma omp atomic capture
213*6ef16f26SJoachim Jenke lcheck = ++checker; // 1 or 2
214*6ef16f26SJoachim Jenke th = omp_get_thread_num();
215*6ef16f26SJoachim Jenke printf("task 1_%d, th %d, checker %d\n", t, th, lcheck);
216*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
217*6ef16f26SJoachim Jenke err++; // no more than 2 tasks concurrently
218*6ef16f26SJoachim Jenke printf("Error3, checker %d, not 1 or 2\n", lcheck);
219*6ef16f26SJoachim Jenke }
220*6ef16f26SJoachim Jenke mysleep(DELAY);
221*6ef16f26SJoachim Jenke #pragma omp atomic read
222*6ef16f26SJoachim Jenke lcheck = checker; // 1 or 2
223*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
224*6ef16f26SJoachim Jenke err++;
225*6ef16f26SJoachim Jenke printf("Error4, checker %d, not 1 or 2\n", lcheck);
226*6ef16f26SJoachim Jenke }
227*6ef16f26SJoachim Jenke #pragma omp atomic
228*6ef16f26SJoachim Jenke --checker;
229*6ef16f26SJoachim Jenke }
230*6ef16f26SJoachim Jenke // compiler codegen start
231*6ef16f26SJoachim Jenke // task2
232*6ef16f26SJoachim Jenke ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);
233*6ef16f26SJoachim Jenke sdep[0].addr = (size_t)&i1;
234*6ef16f26SJoachim Jenke sdep[0].len = 0; // not used
235*6ef16f26SJoachim Jenke sdep[0].flags = 1; // IN
236*6ef16f26SJoachim Jenke sdep[1].addr = (size_t)&i2;
237*6ef16f26SJoachim Jenke sdep[1].len = 0; // not used
238*6ef16f26SJoachim Jenke sdep[1].flags = 8; // INOUTSET
239*6ef16f26SJoachim Jenke ptr->f_priv = t + 10; // init single first-private variable
240*6ef16f26SJoachim Jenke __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);
241*6ef16f26SJoachim Jenke
242*6ef16f26SJoachim Jenke // task3
243*6ef16f26SJoachim Jenke ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);
244*6ef16f26SJoachim Jenke sdep[0].addr = (size_t)&i1; // to be ignored
245*6ef16f26SJoachim Jenke sdep[0].len = 0; // not used
246*6ef16f26SJoachim Jenke sdep[0].flags = 1; // IN
247*6ef16f26SJoachim Jenke sdep[1].addr = 0;
248*6ef16f26SJoachim Jenke sdep[1].len = 0; // not used
249*6ef16f26SJoachim Jenke sdep[1].flags = DEP_ALL_MEM; // omp_all_memory
250*6ef16f26SJoachim Jenke ptr->f_priv = t + 20; // init single first-private variable
251*6ef16f26SJoachim Jenke __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);
252*6ef16f26SJoachim Jenke // compiler codegen end
253*6ef16f26SJoachim Jenke #pragma omp task depend(in : i1, i2)
254*6ef16f26SJoachim Jenke { // task 4
255*6ef16f26SJoachim Jenke int lcheck, th;
256*6ef16f26SJoachim Jenke #pragma omp atomic capture
257*6ef16f26SJoachim Jenke lcheck = ++checker; // 1 or 2
258*6ef16f26SJoachim Jenke th = omp_get_thread_num();
259*6ef16f26SJoachim Jenke printf("task 4_%d, th %d, checker %d\n", t, th, lcheck);
260*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
261*6ef16f26SJoachim Jenke err++; // no more than 2 tasks concurrently
262*6ef16f26SJoachim Jenke printf("Error5, checker %d, not 1 or 2\n", lcheck);
263*6ef16f26SJoachim Jenke }
264*6ef16f26SJoachim Jenke mysleep(DELAY);
265*6ef16f26SJoachim Jenke #pragma omp atomic read
266*6ef16f26SJoachim Jenke lcheck = checker; // 1 or 2
267*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
268*6ef16f26SJoachim Jenke err++;
269*6ef16f26SJoachim Jenke printf("Error6, checker %d, not 1 or 2\n", lcheck);
270*6ef16f26SJoachim Jenke }
271*6ef16f26SJoachim Jenke #pragma omp atomic
272*6ef16f26SJoachim Jenke --checker;
273*6ef16f26SJoachim Jenke }
274*6ef16f26SJoachim Jenke #pragma omp task depend(in : i1, i2)
275*6ef16f26SJoachim Jenke { // task 5
276*6ef16f26SJoachim Jenke int lcheck, th;
277*6ef16f26SJoachim Jenke #pragma omp atomic capture
278*6ef16f26SJoachim Jenke lcheck = ++checker; // 1 or 2
279*6ef16f26SJoachim Jenke th = omp_get_thread_num();
280*6ef16f26SJoachim Jenke printf("task 5_%d, th %d, checker %d\n", t, th, lcheck);
281*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
282*6ef16f26SJoachim Jenke err++; // no more than 2 tasks concurrently
283*6ef16f26SJoachim Jenke printf("Error7, checker %d, not 1 or 2\n", lcheck);
284*6ef16f26SJoachim Jenke }
285*6ef16f26SJoachim Jenke mysleep(DELAY);
286*6ef16f26SJoachim Jenke #pragma omp atomic read
287*6ef16f26SJoachim Jenke lcheck = checker; // 1 or 2
288*6ef16f26SJoachim Jenke if (lcheck > 2 || lcheck < 1) {
289*6ef16f26SJoachim Jenke err++;
290*6ef16f26SJoachim Jenke printf("Error8, checker %d, not 1 or 2\n", lcheck);
291*6ef16f26SJoachim Jenke }
292*6ef16f26SJoachim Jenke #pragma omp atomic
293*6ef16f26SJoachim Jenke --checker;
294*6ef16f26SJoachim Jenke }
295*6ef16f26SJoachim Jenke // compiler codegen start
296*6ef16f26SJoachim Jenke // task6
297*6ef16f26SJoachim Jenke ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);
298*6ef16f26SJoachim Jenke sdep[0].addr = (size_t)(-1); // omp_all_memory
299*6ef16f26SJoachim Jenke sdep[0].len = 0; // not used
300*6ef16f26SJoachim Jenke sdep[0].flags = 2; // OUT
301*6ef16f26SJoachim Jenke ptr->f_priv = t + 30; // init single first-private variable
302*6ef16f26SJoachim Jenke __kmpc_omp_task_with_deps(&loc, gtid, ptr, 1, sdep, 0, 0);
303*6ef16f26SJoachim Jenke
304*6ef16f26SJoachim Jenke // task7
305*6ef16f26SJoachim Jenke ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_m);
306*6ef16f26SJoachim Jenke sdep[0].addr = 0;
307*6ef16f26SJoachim Jenke sdep[0].len = 0; // not used
308*6ef16f26SJoachim Jenke sdep[0].flags = DEP_ALL_MEM; // omp_all_memory
309*6ef16f26SJoachim Jenke sdep[1].addr = (size_t)&i3; // to be ignored
310*6ef16f26SJoachim Jenke sdep[1].len = 0; // not used
311*6ef16f26SJoachim Jenke sdep[1].flags = 4; // MUTEXINOUTSET
312*6ef16f26SJoachim Jenke ptr->f_priv = t + 40; // init single first-private variable
313*6ef16f26SJoachim Jenke __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);
314*6ef16f26SJoachim Jenke // compiler codegen end
315*6ef16f26SJoachim Jenke #pragma omp task depend(in : i3)
316*6ef16f26SJoachim Jenke { // task 8
317*6ef16f26SJoachim Jenke int lcheck, th;
318*6ef16f26SJoachim Jenke #pragma omp atomic capture
319*6ef16f26SJoachim Jenke lcheck = ++checker; // 1
320*6ef16f26SJoachim Jenke th = omp_get_thread_num();
321*6ef16f26SJoachim Jenke printf("task 8_%d, th %d, checker %d\n", t, th, lcheck);
322*6ef16f26SJoachim Jenke if (lcheck != 1) {
323*6ef16f26SJoachim Jenke err++;
324*6ef16f26SJoachim Jenke printf("Error9, checker %d, != 1\n", lcheck);
325*6ef16f26SJoachim Jenke }
326*6ef16f26SJoachim Jenke mysleep(DELAY);
327*6ef16f26SJoachim Jenke #pragma omp atomic read
328*6ef16f26SJoachim Jenke lcheck = checker;
329*6ef16f26SJoachim Jenke if (lcheck != 1) {
330*6ef16f26SJoachim Jenke err++;
331*6ef16f26SJoachim Jenke printf("Error10, checker %d, != 1\n", lcheck);
332*6ef16f26SJoachim Jenke }
333*6ef16f26SJoachim Jenke #pragma omp atomic
334*6ef16f26SJoachim Jenke --checker;
335*6ef16f26SJoachim Jenke }
336*6ef16f26SJoachim Jenke } // single
337*6ef16f26SJoachim Jenke } // parallel
338*6ef16f26SJoachim Jenke if (err == 0 && checker == 0) {
339*6ef16f26SJoachim Jenke printf("passed\n");
340*6ef16f26SJoachim Jenke return 0;
341*6ef16f26SJoachim Jenke } else {
342*6ef16f26SJoachim Jenke printf("failed, err = %d, checker = %d\n", err, checker);
343*6ef16f26SJoachim Jenke return 1;
344*6ef16f26SJoachim Jenke }
345*6ef16f26SJoachim Jenke }
346