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