1// RUN: %libomp-compile-and-run
2
3// Tests OMP 5.0 task dependences "mutexinoutset", emulates compiler codegen
4// Mutually exclusive tasks get input dependency info array sorted differently
5//
6// Task tree created:
7// task0 task1
8// \ / \
9// task2 task5
10// / \
11// task3 task4
12// / \
13// task6 <-->task7 (these two are mutually exclusive)
14// \ /
15// task8
16//
17#include <stdio.h>
18#include <omp.h>
19
20#ifdef _WIN32
21#include <windows.h>
22#define mysleep(n) Sleep(n)
23#else
24#include <unistd.h>
25#define mysleep(n) usleep((n)*1000)
26#endif
27
28static int checker = 0; // to check if two tasks run simultaneously
29static int err = 0;
30#ifndef DELAY
31#define DELAY 100
32#endif
33
34// ---------------------------------------------------------------------------
35// internal data to emulate compiler codegen
36typedef int(*entry_t)(int, int**);
37typedef struct DEP {
38 size_t addr;
39 size_t len;
40 unsigned char flags;
41} dep;
42typedef struct ID {
43 int reserved_1;
44 int flags;
45 int reserved_2;
46 int reserved_3;
47 char *psource;
48} id;
49
50int thunk(int gtid, int** pshareds) {
51 int t = **pshareds;
52 int th = omp_get_thread_num();
53 #pragma omp atomic
54 ++checker;
55 printf(format: "task __%d, th %d\n", t, th);
56 if (checker != 1) {
57 err++;
58 printf(format: "Error1, checker %d != 1\n", checker);
59 }
60 mysleep(DELAY);
61 if (checker != 1) {
62 err++;
63 printf(format: "Error2, checker %d != 1\n", checker);
64 }
65 #pragma omp atomic
66 --checker;
67 return 0;
68}
69
70#ifdef __cplusplus
71extern "C" {
72#endif
73int __kmpc_global_thread_num(id*);
74extern int** __kmpc_omp_task_alloc(id *loc, int gtid, int flags,
75 size_t sz, size_t shar, entry_t rtn);
76int
77__kmpc_omp_task_with_deps(id *loc, int gtid, int **task, int nd, dep *dep_lst,
78 int nd_noalias, dep *noalias_dep_lst);
79static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};
80#ifdef __cplusplus
81} // extern "C"
82#endif
83// End of internal data
84// ---------------------------------------------------------------------------
85
86int main()
87{
88 int i1,i2,i3,i4;
89 omp_set_num_threads(2);
90 #pragma omp parallel
91 {
92 #pragma omp single nowait
93 {
94 dep sdep[2];
95 int **ptr;
96 int gtid = __kmpc_global_thread_num(&loc);
97 int t = omp_get_thread_num();
98 #pragma omp task depend(in: i1, i2)
99 { int th = omp_get_thread_num();
100 printf(format: "task 0_%d, th %d\n", t, th);
101 mysleep(DELAY); }
102 #pragma omp task depend(in: i1, i3)
103 { int th = omp_get_thread_num();
104 printf(format: "task 1_%d, th %d\n", t, th);
105 mysleep(DELAY); }
106 #pragma omp task depend(in: i2) depend(out: i1)
107 { int th = omp_get_thread_num();
108 printf(format: "task 2_%d, th %d\n", t, th);
109 mysleep(DELAY); }
110 #pragma omp task depend(in: i1)
111 { int th = omp_get_thread_num();
112 printf(format: "task 3_%d, th %d\n", t, th);
113 mysleep(DELAY); }
114 #pragma omp task depend(out: i2)
115 { int th = omp_get_thread_num();
116 printf(format: "task 4_%d, th %d\n", t, th);
117 mysleep(DELAY+5); } // wait a bit longer than task 3
118 #pragma omp task depend(out: i3)
119 { int th = omp_get_thread_num();
120 printf(format: "task 5_%d, th %d\n", t, th);
121 mysleep(DELAY); }
122// compiler codegen start
123 // task1
124 ptr = __kmpc_omp_task_alloc(loc: &loc, gtid, flags: 0, sz: 28, shar: 16, rtn: thunk);
125 sdep[0].addr = (size_t)&i1;
126 sdep[0].len = 0; // not used
127 sdep[0].flags = 4; // mx
128 sdep[1].addr = (size_t)&i4;
129 sdep[1].len = 0; // not used
130 sdep[1].flags = 4; // mx
131 **ptr = t + 10; // init single shared variable
132 __kmpc_omp_task_with_deps(loc: &loc, gtid, task: ptr, nd: 2, dep_lst: sdep, nd_noalias: 0, noalias_dep_lst: 0);
133
134 // task2
135 ptr = __kmpc_omp_task_alloc(loc: &loc, gtid, flags: 0, sz: 28, shar: 16, rtn: thunk);
136 // reverse pointers - library should sort them uniquely
137 sdep[0].addr = (size_t)&i4;
138 sdep[1].addr = (size_t)&i1;
139 **ptr = t + 20; // init single shared variable
140 __kmpc_omp_task_with_deps(loc: &loc, gtid, task: ptr, nd: 2, dep_lst: sdep, nd_noalias: 0, noalias_dep_lst: 0);
141// compiler codegen end
142 #pragma omp task depend(in: i1)
143 { int th = omp_get_thread_num();
144 printf(format: "task 8_%d, th %d\n", t, th);
145 mysleep(DELAY); }
146 } // single
147 } // parallel
148 if (err == 0) {
149 printf(format: "passed\n");
150 return 0;
151 } else {
152 printf(format: "failed\n");
153 return 1;
154 }
155}
156

source code of openmp/runtime/test/tasking/omp50_task_depend_mtx2.c