// REQUIRES: linux // RUN: %libomp-compile && env OMP_NUM_THREADS='2' %libomp-run #include #include #include "kmp_task_deps.h" // Expected dependency graph (directed from top to bottom) // // A B C // inoutset(x), inoutset(x, y), inoutset(y) // | \ | / | // D E F // in(x), in(x, y), in(y) // \ / // G // out(y) // the test int main(void) { volatile int done = 0; #pragma omp parallel num_threads(2) { while (omp_get_thread_num() != 0 && !done) ; #pragma omp single { kmp_task_t *A, *B, *C, *D, *E, *F, *G; kmp_depnode_list_t *A_succ, *B_succ, *C_succ, *E_succ, *F_succ; kmp_base_depnode_t *D_node, *E_node, *F_node, *G_node; dep deps[2]; int gtid; int x, y; gtid = __kmpc_global_thread_num(&loc); deps[0].addr = (size_t)&x; deps[0].len = 0; deps[0].flags = 8; // INOUTSET deps[1].addr = (size_t)&y; deps[1].len = 0; deps[1].flags = 8; // INOUTSET // A inoutset(x) A = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, A, 1, deps + 0, 0, 0); // B inoutset(x, y) B = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, B, 2, deps + 0, 0, 0); // C inoutset(y) C = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, C, 1, deps + 1, 0, 0); deps[0].flags = 1; // IN deps[1].flags = 1; // IN // D in(x) D = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, D, 1, deps + 0, 0, 0); // E in(x, y) E = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, E, 2, deps + 0, 0, 0); // F in(y) F = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, F, 1, deps + 1, 0, 0); deps[1].flags = 2; // OUT // G out(y) G = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(kmp_task_t), 0, NULL); __kmpc_omp_task_with_deps(&loc, gtid, G, 1, deps + 1, 0, 0); // Retrieve TDG nodes and check edges A_succ = __kmpc_task_get_successors(A); B_succ = __kmpc_task_get_successors(B); C_succ = __kmpc_task_get_successors(C); E_succ = __kmpc_task_get_successors(E); F_succ = __kmpc_task_get_successors(F); D_node = __kmpc_task_get_depnode(D); E_node = __kmpc_task_get_depnode(E); F_node = __kmpc_task_get_depnode(F); G_node = __kmpc_task_get_depnode(G); // A -> D and A -> E assert(A_succ && A_succ->next && !A_succ->next->next); assert((A_succ->node == D_node && A_succ->next->node == E_node) || (A_succ->node == E_node && A_succ->next->node == D_node)); // B -> D and B -> E and B -> F // valid lists are // (D, E, F) // (D, F, E) // (E, D, F) // (E, F, D) // (F, D, E) // (F, E, D) assert(B_succ && B_succ->next && B_succ->next->next && !B_succ->next->next->next); assert((B_succ->node == D_node && B_succ->next->node == E_node && B_succ->next->next->node == F_node) || (B_succ->node == D_node && B_succ->next->node == F_node && B_succ->next->next->node == E_node) || (B_succ->node == E_node && B_succ->next->node == D_node && B_succ->next->next->node == F_node) || (B_succ->node == E_node && B_succ->next->node == F_node && B_succ->next->next->node == D_node) || (B_succ->node == F_node && B_succ->next->node == D_node && B_succ->next->next->node == E_node) || (B_succ->node == F_node && B_succ->next->node == E_node && B_succ->next->next->node == D_node)); // C -> E and C -> F assert(C_succ && C_succ->next && !C_succ->next->next); assert((C_succ->node == E_node && C_succ->next->node == F_node) || (C_succ->node == F_node && C_succ->next->node == E_node)); // E -> G and F -> G assert(E_succ && !E_succ->next); assert(E_succ->node == G_node); assert(F_succ && !F_succ->next); assert(F_succ->node == G_node); #pragma omp taskwait done = 1; } } return 0; }