xref: /llvm-project/openmp/runtime/test/tasking/kmp_task_deps_multiple_edges_inoutset.c (revision f5e50b21da0cb543064b2d0b9304ce0b368cf2bb)
1 // REQUIRES: linux
2 // RUN: %libomp-compile && env OMP_NUM_THREADS='2' %libomp-run
3 
4 #include <assert.h>
5 #include <omp.h>
6 
7 #include "kmp_task_deps.h"
8 
9 //  Expected dependency graph (directed from top to bottom)
10 //
11 //          A   B   C       // inoutset(x), inoutset(x, y), inoutset(y)
12 //          | \ | / |
13 //          D   E   F       // in(x), in(x, y), in(y)
14 //               \ /
15 //                G         // out(y)
16 
17 // the test
main(void)18 int main(void) {
19   volatile int done = 0;
20 
21 #pragma omp parallel num_threads(2)
22   {
23     while (omp_get_thread_num() != 0 && !done)
24       ;
25 
26 #pragma omp single
27     {
28       kmp_task_t *A, *B, *C, *D, *E, *F, *G;
29       kmp_depnode_list_t *A_succ, *B_succ, *C_succ, *E_succ, *F_succ;
30       kmp_base_depnode_t *D_node, *E_node, *F_node, *G_node;
31       dep deps[2];
32       int gtid;
33       int x, y;
34 
35       gtid = __kmpc_global_thread_num(&loc);
36 
37       deps[0].addr = (size_t)&x;
38       deps[0].len = 0;
39       deps[0].flags = 8; // INOUTSET
40 
41       deps[1].addr = (size_t)&y;
42       deps[1].len = 0;
43       deps[1].flags = 8; // INOUTSET
44 
45       // A inoutset(x)
46       A = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
47       __kmpc_omp_task_with_deps(&loc, gtid, A, 1, deps + 0, 0, 0);
48 
49       // B inoutset(x, y)
50       B = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
51       __kmpc_omp_task_with_deps(&loc, gtid, B, 2, deps + 0, 0, 0);
52 
53       // C inoutset(y)
54       C = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
55       __kmpc_omp_task_with_deps(&loc, gtid, C, 1, deps + 1, 0, 0);
56 
57       deps[0].flags = 1; // IN
58       deps[1].flags = 1; // IN
59 
60       // D in(x)
61       D = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
62       __kmpc_omp_task_with_deps(&loc, gtid, D, 1, deps + 0, 0, 0);
63 
64       // E in(x, y)
65       E = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
66       __kmpc_omp_task_with_deps(&loc, gtid, E, 2, deps + 0, 0, 0);
67 
68       // F in(y)
69       F = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
70       __kmpc_omp_task_with_deps(&loc, gtid, F, 1, deps + 1, 0, 0);
71 
72       deps[1].flags = 2; // OUT
73 
74       // G out(y)
75       G = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL);
76       __kmpc_omp_task_with_deps(&loc, gtid, G, 1, deps + 1, 0, 0);
77 
78       // Retrieve TDG nodes and check edges
79       A_succ = __kmpc_task_get_successors(A);
80       B_succ = __kmpc_task_get_successors(B);
81       C_succ = __kmpc_task_get_successors(C);
82       E_succ = __kmpc_task_get_successors(E);
83       F_succ = __kmpc_task_get_successors(F);
84 
85       D_node = __kmpc_task_get_depnode(D);
86       E_node = __kmpc_task_get_depnode(E);
87       F_node = __kmpc_task_get_depnode(F);
88 
89       G_node = __kmpc_task_get_depnode(G);
90 
91       // A -> D and A -> E
92       assert(A_succ && A_succ->next && !A_succ->next->next);
93       assert((A_succ->node == D_node && A_succ->next->node == E_node) ||
94              (A_succ->node == E_node && A_succ->next->node == D_node));
95 
96       // B -> D and B -> E and B -> F
97       // valid lists are
98       //  (D, E, F)
99       //  (D, F, E)
100       //  (E, D, F)
101       //  (E, F, D)
102       //  (F, D, E)
103       //  (F, E, D)
104       assert(B_succ && B_succ->next && B_succ->next->next &&
105              !B_succ->next->next->next);
106       assert((B_succ->node == D_node && B_succ->next->node == E_node &&
107               B_succ->next->next->node == F_node) ||
108              (B_succ->node == D_node && B_succ->next->node == F_node &&
109               B_succ->next->next->node == E_node) ||
110              (B_succ->node == E_node && B_succ->next->node == D_node &&
111               B_succ->next->next->node == F_node) ||
112              (B_succ->node == E_node && B_succ->next->node == F_node &&
113               B_succ->next->next->node == D_node) ||
114              (B_succ->node == F_node && B_succ->next->node == D_node &&
115               B_succ->next->next->node == E_node) ||
116              (B_succ->node == F_node && B_succ->next->node == E_node &&
117               B_succ->next->next->node == D_node));
118 
119       // C -> E and C -> F
120       assert(C_succ && C_succ->next && !C_succ->next->next);
121       assert((C_succ->node == E_node && C_succ->next->node == F_node) ||
122              (C_succ->node == F_node && C_succ->next->node == E_node));
123 
124       // E -> G and F -> G
125       assert(E_succ && !E_succ->next);
126       assert(E_succ->node == G_node);
127 
128       assert(F_succ && !F_succ->next);
129       assert(F_succ->node == G_node);
130 
131 #pragma omp taskwait
132 
133       done = 1;
134     }
135   }
136   return 0;
137 }
138