xref: /llvm-project/openmp/runtime/test/tasking/omp50_taskwait_depend.c (revision 80256605f8c6aab8cb33ac3a3784aacd005087a3)
19089b4a5SPeyton, Jonathan L // RUN: %libomp-compile-and-run
29089b4a5SPeyton, Jonathan L // UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
3*80256605SAlexey Bataev 
4*80256605SAlexey Bataev // support for taskwait with depend clause introduced in clang-14
5*80256605SAlexey Bataev // UNSUPPORTED: clang-5, clang-6, clang-6, clang-8, clang-9, clang-10, clang-11,
6*80256605SAlexey Bataev // clang-12, clang-13
7*80256605SAlexey Bataev 
89089b4a5SPeyton, Jonathan L // icc does not yet support taskwait with depend clause
9*80256605SAlexey Bataev // XFAIL: icc
109089b4a5SPeyton, Jonathan L 
119089b4a5SPeyton, Jonathan L #include <stdio.h>
129089b4a5SPeyton, Jonathan L #include <stdlib.h>
139089b4a5SPeyton, Jonathan L #include <omp.h>
149089b4a5SPeyton, Jonathan L #include "omp_my_sleep.h"
159089b4a5SPeyton, Jonathan L 
169089b4a5SPeyton, Jonathan L int a = 0, b = 0;
179089b4a5SPeyton, Jonathan L int task_grabbed = 0, task_can_proceed = 0;
189089b4a5SPeyton, Jonathan L int task2_grabbed = 0, task2_can_proceed = 0;
199089b4a5SPeyton, Jonathan L 
wait_on_flag(int * flag)209089b4a5SPeyton, Jonathan L static void wait_on_flag(int *flag) {
219089b4a5SPeyton, Jonathan L   int flag_value;
229089b4a5SPeyton, Jonathan L   int timelimit = 30;
239089b4a5SPeyton, Jonathan L   int secs = 0;
249089b4a5SPeyton, Jonathan L   do {
259089b4a5SPeyton, Jonathan L     #pragma omp atomic read
269089b4a5SPeyton, Jonathan L     flag_value = *flag;
279089b4a5SPeyton, Jonathan L     my_sleep(1.0);
289089b4a5SPeyton, Jonathan L     secs++;
299089b4a5SPeyton, Jonathan L     if (secs == timelimit) {
309089b4a5SPeyton, Jonathan L       fprintf(stderr, "error: timeout in wait_on_flag()\n");
319089b4a5SPeyton, Jonathan L       exit(EXIT_FAILURE);
329089b4a5SPeyton, Jonathan L     }
339089b4a5SPeyton, Jonathan L   } while (flag_value == 0);
349089b4a5SPeyton, Jonathan L }
359089b4a5SPeyton, Jonathan L 
signal_flag(int * flag)369089b4a5SPeyton, Jonathan L static void signal_flag(int *flag) {
379089b4a5SPeyton, Jonathan L   #pragma omp atomic
389089b4a5SPeyton, Jonathan L   (*flag)++;
399089b4a5SPeyton, Jonathan L }
409089b4a5SPeyton, Jonathan L 
main(int argc,char ** argv)419089b4a5SPeyton, Jonathan L int main(int argc, char** argv) {
429089b4a5SPeyton, Jonathan L 
439089b4a5SPeyton, Jonathan L   // Ensure two threads are running
449089b4a5SPeyton, Jonathan L   int num_threads = omp_get_max_threads();
459089b4a5SPeyton, Jonathan L   if (num_threads < 2)
469089b4a5SPeyton, Jonathan L     omp_set_num_threads(2);
479089b4a5SPeyton, Jonathan L 
489089b4a5SPeyton, Jonathan L   #pragma omp parallel shared(a)
499089b4a5SPeyton, Jonathan L   {
509089b4a5SPeyton, Jonathan L     int a_value;
519089b4a5SPeyton, Jonathan L     // Let us be extra safe here
529089b4a5SPeyton, Jonathan L     if (omp_get_num_threads() > 1) {
539089b4a5SPeyton, Jonathan L       #pragma omp single nowait
549089b4a5SPeyton, Jonathan L       {
559089b4a5SPeyton, Jonathan L         // Schedule independent child task that
569089b4a5SPeyton, Jonathan L         // waits to be flagged after sebsequent taskwait depend()
579089b4a5SPeyton, Jonathan L         #pragma omp task
589089b4a5SPeyton, Jonathan L         {
599089b4a5SPeyton, Jonathan L           signal_flag(&task_grabbed);
609089b4a5SPeyton, Jonathan L           wait_on_flag(&task_can_proceed);
619089b4a5SPeyton, Jonathan L         }
629089b4a5SPeyton, Jonathan L         // Let another worker thread grab the task to execute
639089b4a5SPeyton, Jonathan L         wait_on_flag(&task_grabbed);
649089b4a5SPeyton, Jonathan L         // This should be ignored since the task above has
659089b4a5SPeyton, Jonathan L         // no dependency information
669089b4a5SPeyton, Jonathan L         #pragma omp taskwait depend(inout: a)
679089b4a5SPeyton, Jonathan L         // Signal the independent task to proceed
689089b4a5SPeyton, Jonathan L         signal_flag(&task_can_proceed);
699089b4a5SPeyton, Jonathan L 
709089b4a5SPeyton, Jonathan L         // Schedule child task with dependencies that taskwait does
719089b4a5SPeyton, Jonathan L         // not care about
729089b4a5SPeyton, Jonathan L         #pragma omp task depend(inout: b)
739089b4a5SPeyton, Jonathan L         {
749089b4a5SPeyton, Jonathan L           signal_flag(&task2_grabbed);
759089b4a5SPeyton, Jonathan L           wait_on_flag(&task2_can_proceed);
769089b4a5SPeyton, Jonathan L           #pragma omp atomic
779089b4a5SPeyton, Jonathan L           b++;
789089b4a5SPeyton, Jonathan L         }
799089b4a5SPeyton, Jonathan L         // Let another worker thread grab the task to execute
809089b4a5SPeyton, Jonathan L         wait_on_flag(&task2_grabbed);
819089b4a5SPeyton, Jonathan L         // This should be ignored since the task above has
829089b4a5SPeyton, Jonathan L         // dependency information on b instead of a
839089b4a5SPeyton, Jonathan L         #pragma omp taskwait depend(inout: a)
849089b4a5SPeyton, Jonathan L         // Signal the task to proceed
859089b4a5SPeyton, Jonathan L         signal_flag(&task2_can_proceed);
869089b4a5SPeyton, Jonathan L 
879089b4a5SPeyton, Jonathan L         // Generate one child task for taskwait
889089b4a5SPeyton, Jonathan L         #pragma omp task shared(a) depend(inout: a)
899089b4a5SPeyton, Jonathan L         {
909089b4a5SPeyton, Jonathan L           my_sleep(1.0);
919089b4a5SPeyton, Jonathan L           #pragma omp atomic
929089b4a5SPeyton, Jonathan L           a++;
939089b4a5SPeyton, Jonathan L         }
949089b4a5SPeyton, Jonathan L         #pragma omp taskwait depend(inout: a)
959089b4a5SPeyton, Jonathan L 
969089b4a5SPeyton, Jonathan L         #pragma omp atomic read
979089b4a5SPeyton, Jonathan L         a_value = a;
989089b4a5SPeyton, Jonathan L 
999089b4a5SPeyton, Jonathan L         if (a_value != 1) {
1009089b4a5SPeyton, Jonathan L           fprintf(stderr, "error: dependent task was not executed before "
1019089b4a5SPeyton, Jonathan L                           "taskwait finished\n");
1029089b4a5SPeyton, Jonathan L           exit(EXIT_FAILURE);
1039089b4a5SPeyton, Jonathan L         }
1049089b4a5SPeyton, Jonathan L       } // #pragma omp single
1059089b4a5SPeyton, Jonathan L     } // if (num_threads > 1)
1069089b4a5SPeyton, Jonathan L   } // #pragma omp parallel
1079089b4a5SPeyton, Jonathan L 
1089089b4a5SPeyton, Jonathan L   return EXIT_SUCCESS;
1099089b4a5SPeyton, Jonathan L }
110