1*6d9eb7e7SAndreyChurbanov // RUN: %libomp-compile && env OMP_MAX_TASK_PRIORITY='2' %libomp-run
2*6d9eb7e7SAndreyChurbanov
3*6d9eb7e7SAndreyChurbanov // Test OMP 4.5 task priorities
4*6d9eb7e7SAndreyChurbanov // Higher priority task supposed to be executed before lower priority task.
5*6d9eb7e7SAndreyChurbanov
6*6d9eb7e7SAndreyChurbanov #include <stdio.h>
7*6d9eb7e7SAndreyChurbanov #include <omp.h>
8*6d9eb7e7SAndreyChurbanov
9*6d9eb7e7SAndreyChurbanov #include "omp_my_sleep.h"
10*6d9eb7e7SAndreyChurbanov // delay(n) - sleep n ms
11*6d9eb7e7SAndreyChurbanov #define delay(n) my_sleep(((double)n)/1000.0)
12*6d9eb7e7SAndreyChurbanov
main(void)13*6d9eb7e7SAndreyChurbanov int main ( void ) {
14*6d9eb7e7SAndreyChurbanov int passed;
15*6d9eb7e7SAndreyChurbanov passed = (omp_get_max_task_priority() == 2);
16*6d9eb7e7SAndreyChurbanov printf("Got %d max priority via env\n", omp_get_max_task_priority());
17*6d9eb7e7SAndreyChurbanov if(!passed) {
18*6d9eb7e7SAndreyChurbanov printf( "failed\n" );
19*6d9eb7e7SAndreyChurbanov return 1;
20*6d9eb7e7SAndreyChurbanov }
21*6d9eb7e7SAndreyChurbanov printf("parallel 1 spawns 4 tasks for primary thread to execute\n");
22*6d9eb7e7SAndreyChurbanov #pragma omp parallel num_threads(2)
23*6d9eb7e7SAndreyChurbanov {
24*6d9eb7e7SAndreyChurbanov int th = omp_get_thread_num();
25*6d9eb7e7SAndreyChurbanov if (th == 0) // primary thread
26*6d9eb7e7SAndreyChurbanov {
27*6d9eb7e7SAndreyChurbanov #pragma omp task priority(1)
28*6d9eb7e7SAndreyChurbanov { // middle priority
29*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
30*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
31*6d9eb7e7SAndreyChurbanov val = passed++;
32*6d9eb7e7SAndreyChurbanov printf("P1: val = %d, thread gen %d, thread exe %d\n", val, th, t);
33*6d9eb7e7SAndreyChurbanov delay(10); // sleep 10 ms
34*6d9eb7e7SAndreyChurbanov }
35*6d9eb7e7SAndreyChurbanov #pragma omp task priority(2)
36*6d9eb7e7SAndreyChurbanov { // high priority
37*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
38*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
39*6d9eb7e7SAndreyChurbanov val = passed++;
40*6d9eb7e7SAndreyChurbanov printf("P2: val = %d, thread gen %d, thread exe %d\n", val, th, t);
41*6d9eb7e7SAndreyChurbanov delay(20); // sleep 20 ms
42*6d9eb7e7SAndreyChurbanov }
43*6d9eb7e7SAndreyChurbanov #pragma omp task priority(0)
44*6d9eb7e7SAndreyChurbanov { // low priority specified explicitly
45*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
46*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
47*6d9eb7e7SAndreyChurbanov val = passed++;
48*6d9eb7e7SAndreyChurbanov printf("P0exp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
49*6d9eb7e7SAndreyChurbanov delay(1); // sleep 1 ms
50*6d9eb7e7SAndreyChurbanov }
51*6d9eb7e7SAndreyChurbanov #pragma omp task
52*6d9eb7e7SAndreyChurbanov { // low priority by default
53*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
54*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
55*6d9eb7e7SAndreyChurbanov val = passed++;
56*6d9eb7e7SAndreyChurbanov printf("P0imp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
57*6d9eb7e7SAndreyChurbanov delay(1); // sleep 1 ms
58*6d9eb7e7SAndreyChurbanov }
59*6d9eb7e7SAndreyChurbanov } else {
60*6d9eb7e7SAndreyChurbanov // wait for the primary thread to finish all tasks
61*6d9eb7e7SAndreyChurbanov int wait = 0;
62*6d9eb7e7SAndreyChurbanov do {
63*6d9eb7e7SAndreyChurbanov delay(5);
64*6d9eb7e7SAndreyChurbanov #pragma omp atomic read
65*6d9eb7e7SAndreyChurbanov wait = passed;
66*6d9eb7e7SAndreyChurbanov } while (wait < 5);
67*6d9eb7e7SAndreyChurbanov }
68*6d9eb7e7SAndreyChurbanov }
69*6d9eb7e7SAndreyChurbanov printf("parallel 2 spawns 4 tasks for worker thread to execute\n");
70*6d9eb7e7SAndreyChurbanov #pragma omp parallel num_threads(2)
71*6d9eb7e7SAndreyChurbanov {
72*6d9eb7e7SAndreyChurbanov int th = omp_get_thread_num();
73*6d9eb7e7SAndreyChurbanov if (th == 0) // primary thread
74*6d9eb7e7SAndreyChurbanov {
75*6d9eb7e7SAndreyChurbanov #pragma omp task priority(1)
76*6d9eb7e7SAndreyChurbanov { // middle priority
77*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
78*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
79*6d9eb7e7SAndreyChurbanov val = passed++;
80*6d9eb7e7SAndreyChurbanov printf("P1: val = %d, thread gen %d, thread exe %d\n", val, th, t);
81*6d9eb7e7SAndreyChurbanov delay(10); // sleep 10 ms
82*6d9eb7e7SAndreyChurbanov }
83*6d9eb7e7SAndreyChurbanov #pragma omp task priority(2)
84*6d9eb7e7SAndreyChurbanov { // high priority
85*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
86*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
87*6d9eb7e7SAndreyChurbanov val = passed++;
88*6d9eb7e7SAndreyChurbanov printf("P2: val = %d, thread gen %d, thread exe %d\n", val, th, t);
89*6d9eb7e7SAndreyChurbanov delay(20); // sleep 20 ms
90*6d9eb7e7SAndreyChurbanov }
91*6d9eb7e7SAndreyChurbanov #pragma omp task priority(0)
92*6d9eb7e7SAndreyChurbanov { // low priority specified explicitly
93*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
94*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
95*6d9eb7e7SAndreyChurbanov val = passed++;
96*6d9eb7e7SAndreyChurbanov printf("P0exp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
97*6d9eb7e7SAndreyChurbanov delay(1); // sleep 1 ms
98*6d9eb7e7SAndreyChurbanov }
99*6d9eb7e7SAndreyChurbanov #pragma omp task
100*6d9eb7e7SAndreyChurbanov { // low priority by default
101*6d9eb7e7SAndreyChurbanov int val, t = omp_get_thread_num();
102*6d9eb7e7SAndreyChurbanov #pragma omp atomic capture
103*6d9eb7e7SAndreyChurbanov val = passed++;
104*6d9eb7e7SAndreyChurbanov printf("P0imp: val = %d, thread gen %d, thread exe %d\n", val, th, t);
105*6d9eb7e7SAndreyChurbanov delay(1); // sleep 1 ms
106*6d9eb7e7SAndreyChurbanov }
107*6d9eb7e7SAndreyChurbanov // signal creation of all tasks: passed = 5 + 1 = 6
108*6d9eb7e7SAndreyChurbanov #pragma omp atomic
109*6d9eb7e7SAndreyChurbanov passed++;
110*6d9eb7e7SAndreyChurbanov // wait for completion of all 4 tasks
111*6d9eb7e7SAndreyChurbanov int wait = 0;
112*6d9eb7e7SAndreyChurbanov do {
113*6d9eb7e7SAndreyChurbanov delay(5);
114*6d9eb7e7SAndreyChurbanov #pragma omp atomic read
115*6d9eb7e7SAndreyChurbanov wait = passed;
116*6d9eb7e7SAndreyChurbanov } while (wait < 10); // passed = 6 + 4 = 10
117*6d9eb7e7SAndreyChurbanov } else {
118*6d9eb7e7SAndreyChurbanov // wait for the primary thread to create all tasks
119*6d9eb7e7SAndreyChurbanov int wait = 0;
120*6d9eb7e7SAndreyChurbanov do {
121*6d9eb7e7SAndreyChurbanov delay(5);
122*6d9eb7e7SAndreyChurbanov #pragma omp atomic read
123*6d9eb7e7SAndreyChurbanov wait = passed;
124*6d9eb7e7SAndreyChurbanov } while (wait < 6);
125*6d9eb7e7SAndreyChurbanov // go execute 4 tasks created by primary thread
126*6d9eb7e7SAndreyChurbanov }
127*6d9eb7e7SAndreyChurbanov }
128*6d9eb7e7SAndreyChurbanov if (passed != 10) {
129*6d9eb7e7SAndreyChurbanov printf("failed, passed = %d (should be 10)\n", passed);
130*6d9eb7e7SAndreyChurbanov return 1;
131*6d9eb7e7SAndreyChurbanov }
132*6d9eb7e7SAndreyChurbanov printf("passed\n");
133*6d9eb7e7SAndreyChurbanov return 0;
134*6d9eb7e7SAndreyChurbanov }
135*6d9eb7e7SAndreyChurbanov // CHECK: parallel 1
136*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P2
137*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P1
138*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P0
139*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P0
140*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: parallel 2
141*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P2
142*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P1
143*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P0
144*6d9eb7e7SAndreyChurbanov // CHECK-NEXT: P0
145*6d9eb7e7SAndreyChurbanov // CHECK: passed
146