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