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 |
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: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
47 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: A, nd: 1, dep_lst: deps + 0, nd_noalias: 0, noalias_dep_lst: 0); |
48 | |
49 | // B inoutset(x, y) |
50 | B = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
51 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: B, nd: 2, dep_lst: deps + 0, nd_noalias: 0, noalias_dep_lst: 0); |
52 | |
53 | // C inoutset(y) |
54 | C = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
55 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: C, nd: 1, dep_lst: deps + 1, nd_noalias: 0, noalias_dep_lst: 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: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
62 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: D, nd: 1, dep_lst: deps + 0, nd_noalias: 0, noalias_dep_lst: 0); |
63 | |
64 | // E in(x, y) |
65 | E = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
66 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: E, nd: 2, dep_lst: deps + 0, nd_noalias: 0, noalias_dep_lst: 0); |
67 | |
68 | // F in(y) |
69 | F = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
70 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: F, nd: 1, dep_lst: deps + 1, nd_noalias: 0, noalias_dep_lst: 0); |
71 | |
72 | deps[1].flags = 2; // OUT |
73 | |
74 | // G out(y) |
75 | G = __kmpc_omp_task_alloc(loc: &loc, gtid, TIED, sz: sizeof(kmp_task_t), shar: 0, NULL); |
76 | __kmpc_omp_task_with_deps(loc: &loc, gtid, task: G, nd: 1, dep_lst: deps + 1, nd_noalias: 0, noalias_dep_lst: 0); |
77 | |
78 | // Retrieve TDG nodes and check edges |
79 | A_succ = __kmpc_task_get_successors(task: A); |
80 | B_succ = __kmpc_task_get_successors(task: B); |
81 | C_succ = __kmpc_task_get_successors(task: C); |
82 | E_succ = __kmpc_task_get_successors(task: E); |
83 | F_succ = __kmpc_task_get_successors(task: F); |
84 | |
85 | D_node = __kmpc_task_get_depnode(task: D); |
86 | E_node = __kmpc_task_get_depnode(task: E); |
87 | F_node = __kmpc_task_get_depnode(task: F); |
88 | |
89 | G_node = __kmpc_task_get_depnode(task: 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 | |