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 16 int a = 0, b = 0; 17 int task_grabbed = 0, task_can_proceed = 0; 18 int task2_grabbed = 0, task2_can_proceed = 0; 19 20 static 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, "error: timeout in wait_on_flag()\n"); 31 exit(EXIT_FAILURE); 32 } 33 } while (flag_value == 0); 34 } 35 36 static void signal_flag(int *flag) { 37 #pragma omp atomic 38 (*flag)++; 39 } 40 41 int 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(&task_grabbed); 60 wait_on_flag(&task_can_proceed); 61 } 62 // Let another worker thread grab the task to execute 63 wait_on_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(&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(&task2_grabbed); 75 wait_on_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(&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(&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, "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