1// RUN: %libomp-compile-and-run
2// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
3
4// support for taskwait with depend clause introduced in clang-14
5// UNSUPPORTED: clang-5, clang-6, clang-6, clang-8, clang-9, clang-10, clang-11,
6// clang-12, clang-13
7
8// icc does not yet support taskwait with depend clause
9// XFAIL: icc
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <omp.h>
14#include "omp_my_sleep.h"
15
16int a = 0, b = 0;
17int task_grabbed = 0, task_can_proceed = 0;
18int task2_grabbed = 0, task2_can_proceed = 0;
19
20static void wait_on_flag(int *flag) {
21 int flag_value;
22 int timelimit = 30;
23 int secs = 0;
24 do {
25 #pragma omp atomic read
26 flag_value = *flag;
27 my_sleep(1.0);
28 secs++;
29 if (secs == timelimit) {
30 fprintf(stderr, format: "error: timeout in wait_on_flag()\n");
31 exit(EXIT_FAILURE);
32 }
33 } while (flag_value == 0);
34}
35
36static void signal_flag(int *flag) {
37 #pragma omp atomic
38 (*flag)++;
39}
40
41int main(int argc, char** argv) {
42
43 // Ensure two threads are running
44 int num_threads = omp_get_max_threads();
45 if (num_threads < 2)
46 omp_set_num_threads(2);
47
48 #pragma omp parallel shared(a)
49 {
50 int a_value;
51 // Let us be extra safe here
52 if (omp_get_num_threads() > 1) {
53 #pragma omp single nowait
54 {
55 // Schedule independent child task that
56 // waits to be flagged after sebsequent taskwait depend()
57 #pragma omp task
58 {
59 signal_flag(flag: &task_grabbed);
60 wait_on_flag(flag: &task_can_proceed);
61 }
62 // Let another worker thread grab the task to execute
63 wait_on_flag(flag: &task_grabbed);
64 // This should be ignored since the task above has
65 // no dependency information
66 #pragma omp taskwait depend(inout: a)
67 // Signal the independent task to proceed
68 signal_flag(flag: &task_can_proceed);
69
70 // Schedule child task with dependencies that taskwait does
71 // not care about
72 #pragma omp task depend(inout: b)
73 {
74 signal_flag(flag: &task2_grabbed);
75 wait_on_flag(flag: &task2_can_proceed);
76 #pragma omp atomic
77 b++;
78 }
79 // Let another worker thread grab the task to execute
80 wait_on_flag(flag: &task2_grabbed);
81 // This should be ignored since the task above has
82 // dependency information on b instead of a
83 #pragma omp taskwait depend(inout: a)
84 // Signal the task to proceed
85 signal_flag(flag: &task2_can_proceed);
86
87 // Generate one child task for taskwait
88 #pragma omp task shared(a) depend(inout: a)
89 {
90 my_sleep(1.0);
91 #pragma omp atomic
92 a++;
93 }
94 #pragma omp taskwait depend(inout: a)
95
96 #pragma omp atomic read
97 a_value = a;
98
99 if (a_value != 1) {
100 fprintf(stderr, format: "error: dependent task was not executed before "
101 "taskwait finished\n");
102 exit(EXIT_FAILURE);
103 }
104 } // #pragma omp single
105 } // if (num_threads > 1)
106 } // #pragma omp parallel
107
108 return EXIT_SUCCESS;
109}
110

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