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)
82static int checker = 0;
83static int err = 0;
84#ifndef DELAY
85#define DELAY 100
86#endif
87
88// ---------------------------------------------------------------------------
89// internal data to emulate compiler codegen
90typedef struct DEP {
91 size_t addr;
92 size_t len;
93 unsigned char flags;
94} dep;
95#define DEP_ALL_MEM 0x80
96typedef 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
106typedef int (*entry_t)(int, task_t *);
107typedef 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
115int 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(format: "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(format: "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(format: "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
137int 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(format: "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(format: "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(format: "Error s2, checker %d != 1\n", lcheck);
153 }
154#pragma omp atomic
155 --checker;
156 return 0;
157}
158
159#ifdef __cplusplus
160extern "C" {
161#endif
162int __kmpc_global_thread_num(id *);
163task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,
164 size_t shar, entry_t rtn);
165int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,
166 dep *dep_lst, int nd_noalias, dep *noalias_lst);
167static id loc = {.reserved_1: 0, .flags: 2, .reserved_2: 0, .reserved_3: 0, .psource: ";file;func;0;0;;"};
168#ifdef __cplusplus
169} // extern "C"
170#endif
171// End of internal data
172// ---------------------------------------------------------------------------
173
174int 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(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#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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "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(format: "task 8_%d, th %d, checker %d\n", t, th, lcheck);
358 if (lcheck != 1) {
359 err++;
360 printf(format: "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(format: "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(format: "passed\n");
376 return 0;
377 } else {
378 printf(format: "failed, err = %d, checker = %d\n", err, checker);
379 return 1;
380 }
381}
382

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