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