xref: /llvm-project/openmp/runtime/test/tasking/omp50_task_depend_mtx2.c (revision 77c2b623ca4ce10ec1019b31706a055aad2580cd)
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 
28 static int checker = 0; // to check if two tasks run simultaneously
29 static int err = 0;
30 #ifndef DELAY
31 #define DELAY 100
32 #endif
33 
34 // ---------------------------------------------------------------------------
35 // internal data to emulate compiler codegen
36 typedef int(*entry_t)(int, int**);
37 typedef struct DEP {
38   size_t addr;
39   size_t len;
40   unsigned char flags;
41 } dep;
42 typedef struct ID {
43   int reserved_1;
44   int flags;
45   int reserved_2;
46   int reserved_3;
47   char *psource;
48 } id;
49 
thunk(int gtid,int ** pshareds)50 int thunk(int gtid, int** pshareds) {
51   int t = **pshareds;
52   int th = omp_get_thread_num();
53   #pragma omp atomic
54     ++checker;
55   printf("task __%d, th %d\n", t, th);
56   if (checker != 1) {
57     err++;
58     printf("Error1, checker %d != 1\n", checker);
59   }
60   mysleep(DELAY);
61   if (checker != 1) {
62     err++;
63     printf("Error2, checker %d != 1\n", checker);
64   }
65   #pragma omp atomic
66     --checker;
67   return 0;
68 }
69 
70 #ifdef __cplusplus
71 extern "C" {
72 #endif
73 int __kmpc_global_thread_num(id*);
74 extern int** __kmpc_omp_task_alloc(id *loc, int gtid, int flags,
75                                    size_t sz, size_t shar, entry_t rtn);
76 int
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);
79 static 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 
main()86 int 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("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("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("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("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("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("task 5_%d, th %d\n", t, th);
121         mysleep(DELAY); }
122 // compiler codegen start
123       // task1
124       ptr = __kmpc_omp_task_alloc(&loc, gtid, 0, 28, 16, 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, gtid, ptr, 2, sdep, 0, 0);
133 
134       // task2
135       ptr = __kmpc_omp_task_alloc(&loc, gtid, 0, 28, 16, 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, gtid, ptr, 2, sdep, 0, 0);
141 // compiler codegen end
142       #pragma omp task depend(in: i1)
143       { int th = omp_get_thread_num();
144         printf("task 8_%d, th %d\n", t, th);
145         mysleep(DELAY); }
146     } // single
147   } // parallel
148   if (err == 0) {
149     printf("passed\n");
150     return 0;
151   } else {
152     printf("failed\n");
153     return 1;
154   }
155 }
156