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)
83static int checker = 0;
84static int err = 0;
85#ifndef DELAY
86#define DELAY 100
87#endif
88
89// ---------------------------------------------------------------------------
90// internal data to emulate compiler codegen
91typedef struct DEP {
92 size_t addr;
93 size_t len;
94 unsigned char flags;
95} dep;
96#define DEP_ALL_MEM 0x80
97typedef 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
107typedef int (*entry_t)(int, task_t *);
108typedef 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
116int 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(format: "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(format: "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(format: "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
138int 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(format: "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(format: "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(format: "Error s2, checker %d != 1\n", lcheck);
154 }
155#pragma omp atomic
156 --checker;
157 return 0;
158}
159
160#ifdef __cplusplus
161extern "C" {
162#endif
163int __kmpc_global_thread_num(id *);
164task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,
165 size_t shar, entry_t rtn);
166int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,
167 dep *dep_lst, int nd_noalias, dep *noalias_lst);
168static id loc = {.reserved_1: 0, .flags: 2, .reserved_2: 0, .reserved_3: 0, .psource: ";file;func;0;0;;"};
169#ifdef __cplusplus
170} // extern "C"
171#endif
172// End of internal data
173// ---------------------------------------------------------------------------
174
175int 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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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: &loc, gtid, TIED, sz: sizeof(task_t), shar: 0, rtn: 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: &loc, gtid, task: ptr, ndeps: 2, dep_lst: sdep, nd_noalias: 0, noalias_lst: 0);
241
242 // task3
243 ptr = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(task_t), shar: 0, rtn: 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: &loc, gtid, task: ptr, ndeps: 2, dep_lst: sdep, nd_noalias: 0, noalias_lst: 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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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: &loc, gtid, TIED, sz: sizeof(task_t), shar: 0, rtn: 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: &loc, gtid, task: ptr, ndeps: 1, dep_lst: sdep, nd_noalias: 0, noalias_lst: 0);
303
304 // task7
305 ptr = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(task_t), shar: 0, rtn: 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: &loc, gtid, task: ptr, ndeps: 2, dep_lst: sdep, nd_noalias: 0, noalias_lst: 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(format: "task 8_%d, th %d, checker %d\n", t, th, lcheck);
322 if (lcheck != 1) {
323 err++;
324 printf(format: "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(format: "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(format: "passed\n");
340 return 0;
341 } else {
342 printf(format: "failed, err = %d, checker = %d\n", err, checker);
343 return 1;
344 }
345}
346

source code of openmp/runtime/test/ompt/tasks/kmp_task_depend_all.c