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
18int 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

source code of openmp/runtime/test/tasking/kmp_task_deps_multiple_edges_inoutset.c