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