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