| // RUN: %libomp-compile-and-run | 
 |  | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <omp.h> | 
 | #include "omp_my_sleep.h" | 
 |  | 
 | int a = 0, b = 0; | 
 | int task_grabbed = 0, task_can_proceed = 0; | 
 | int task2_grabbed = 0, task2_can_proceed = 0; | 
 |  | 
 | static void wait_on_flag(int *flag) { | 
 |   int flag_value; | 
 |   int timelimit = 30; | 
 |   int secs = 0; | 
 |   do { | 
 |     #pragma omp atomic read | 
 |     flag_value = *flag; | 
 |     my_sleep(1.0); | 
 |     secs++; | 
 |     if (secs == timelimit) { | 
 |       fprintf(stderr, "error: timeout in wait_on_flag()\n"); | 
 |       exit(EXIT_FAILURE); | 
 |     } | 
 |   } while (flag_value == 0); | 
 | } | 
 |  | 
 | static void signal_flag(int *flag) { | 
 |   #pragma omp atomic | 
 |   (*flag)++; | 
 | } | 
 |  | 
 | int main(int argc, char** argv) { | 
 |  | 
 |   // Ensure two threads are running | 
 |   int num_threads = omp_get_max_threads(); | 
 |   if (num_threads < 2) | 
 |     omp_set_num_threads(2); | 
 |  | 
 |   #pragma omp parallel shared(a) | 
 |   { | 
 |     int a_value; | 
 |     // Let us be extra safe here | 
 |     if (omp_get_num_threads() > 1) { | 
 |       #pragma omp single nowait | 
 |       { | 
 |         // Schedule independent child task that | 
 |         // waits to be flagged after sebsequent taskwait depend() | 
 |         #pragma omp task | 
 |         { | 
 |           signal_flag(&task_grabbed); | 
 |           wait_on_flag(&task_can_proceed); | 
 |         } | 
 |         // Let another worker thread grab the task to execute | 
 |         wait_on_flag(&task_grabbed); | 
 |         // This should be ignored since the task above has | 
 |         // no dependency information | 
 |         #pragma omp task if(0) depend(inout: a) | 
 |         {} | 
 |         // Signal the independent task to proceed | 
 |         signal_flag(&task_can_proceed); | 
 |  | 
 |         // Schedule child task with dependencies that taskwait does | 
 |         // not care about | 
 |         #pragma omp task depend(inout: b) | 
 |         { | 
 |           signal_flag(&task2_grabbed); | 
 |           wait_on_flag(&task2_can_proceed); | 
 |           #pragma omp atomic | 
 |           b++; | 
 |         } | 
 |         // Let another worker thread grab the task to execute | 
 |         wait_on_flag(&task2_grabbed); | 
 |         // This should be ignored since the task above has | 
 |         // dependency information on b instead of a | 
 |         #pragma omp task if(0) depend(inout: a) | 
 |         {} | 
 |         // Signal the task to proceed | 
 |         signal_flag(&task2_can_proceed); | 
 |  | 
 |         // Generate one child task for taskwait | 
 |         #pragma omp task shared(a) depend(inout: a) | 
 |         { | 
 |           my_sleep(1.0); | 
 |           #pragma omp atomic | 
 |           a++; | 
 |         } | 
 |         #pragma omp task if(0) depend(inout: a) | 
 |         {} | 
 |  | 
 |         #pragma omp atomic read | 
 |         a_value = a; | 
 |  | 
 |         if (a_value != 1) { | 
 |           fprintf(stderr, "error: dependent task was not executed before " | 
 |                           "taskwait finished\n"); | 
 |           exit(EXIT_FAILURE); | 
 |         } | 
 |       } // #pragma omp single | 
 |     } // if (num_threads > 1) | 
 |   } // #pragma omp parallel | 
 |  | 
 |   return EXIT_SUCCESS; | 
 | } |