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