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