1 // RUN: %libomp-compile-and-run
2 // UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
3 // UNSUPPORTED: clang-3, clang-4, clang-5, clang-6, clang-7, clang-8
4 // TODO: update expected result when icc supports mutexinoutset
5 // XFAIL: icc
6 
7 // Tests OMP 5.0 task dependences "mutexinoutset", emulates compiler codegen
8 // Mutually exclusive tasks get same input dependency info array
9 //
10 // Task tree created:
11 //      task0 task1
12 //         \    / \
13 //         task2   task5
14 //           / \
15 //       task3  task4
16 //       /   \
17 //  task6 <-->task7  (these two are mutually exclusive)
18 //       \    /
19 //       task8
20 //
21 #include <stdio.h>
22 #include <omp.h>
23 #include "omp_my_sleep.h"
24 
25 static int checker = 0; // to check if two tasks run simultaneously
26 static int err = 0;
27 #ifndef DELAY
28 #define DELAY 0.1
29 #endif
30 
mutex_task(int task_id)31 int mutex_task(int task_id) {
32   int th = omp_get_thread_num();
33   #pragma omp atomic
34     ++checker;
35   printf("task %d, th %d\n", task_id, th);
36   if (checker != 1) {
37     err++;
38     printf("Error1, checker %d != 1\n", checker);
39   }
40   my_sleep(DELAY);
41   if (checker != 1) {
42     err++;
43     printf("Error2, checker %d != 1\n", checker);
44   }
45   #pragma omp atomic
46     --checker;
47   return 0;
48 }
49 
main()50 int main()
51 {
52   int i1,i2,i3,i4;
53   omp_set_num_threads(2);
54   #pragma omp parallel
55   {
56     #pragma omp single nowait
57     {
58       int t = omp_get_thread_num();
59       #pragma omp task depend(in: i1, i2)
60       { int th = omp_get_thread_num();
61         printf("task 0_%d, th %d\n", t, th);
62         my_sleep(DELAY); }
63       #pragma omp task depend(in: i1, i3)
64       { int th = omp_get_thread_num();
65         printf("task 1_%d, th %d\n", t, th);
66         my_sleep(DELAY); }
67       #pragma omp task depend(in: i2) depend(out: i1)
68       { int th = omp_get_thread_num();
69         printf("task 2_%d, th %d\n", t, th);
70         my_sleep(DELAY); }
71       #pragma omp task depend(in: i1)
72       { int th = omp_get_thread_num();
73         printf("task 3_%d, th %d\n", t, th);
74         my_sleep(DELAY); }
75       #pragma omp task depend(out: i2)
76       { int th = omp_get_thread_num();
77         printf("task 4_%d, th %d\n", t, th);
78         my_sleep(DELAY+0.1); } // wait a bit longer than task 3
79       #pragma omp task depend(out: i3)
80       { int th = omp_get_thread_num();
81         printf("task 5_%d, th %d\n", t, th);
82         my_sleep(DELAY); }
83 
84       #pragma omp task depend(mutexinoutset: i1, i4)
85       { mutex_task(6); }
86       #pragma omp task depend(mutexinoutset: i1, i4)
87       { mutex_task(7); }
88 
89       #pragma omp task depend(in: i1)
90       { int th = omp_get_thread_num();
91         printf("task 8_%d, th %d\n", t, th);
92         my_sleep(DELAY); }
93     } // single
94   } // parallel
95   if (err == 0) {
96     printf("passed\n");
97     return 0;
98   } else {
99     printf("failed\n");
100     return 1;
101   }
102 }
103