Skip to content

Commit ee1c04a

Browse files
author
Peyton, Jonathan L
committed
[OpenMP] Fix if0 task with dependencies in the runtime
The current GOMP interface for serialized tasks does not take into account task dependencies. Add the check and wait for dependencies. Fixes: https://bugs.llvm.org/show_bug.cgi?id=46573 Differential Revision: https://reviews.llvm.org/D87271
1 parent 9089b4a commit ee1c04a

File tree

3 files changed

+161
-3
lines changed

3 files changed

+161
-3
lines changed

openmp/runtime/src/kmp_gsupport.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
#include "ompt-specific.h"
1818
#endif
1919

20+
enum {
21+
KMP_GOMP_TASK_UNTIED_FLAG = 1,
22+
KMP_GOMP_TASK_FINAL_FLAG = 2,
23+
KMP_GOMP_TASK_DEPENDS_FLAG = 8
24+
};
25+
2026
// This class helps convert gomp dependency info into
2127
// kmp_depend_info_t structures
2228
class kmp_gomp_depends_info_t {
@@ -1181,11 +1187,11 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
11811187
KA_TRACE(20, ("GOMP_task: T#%d\n", gtid));
11821188

11831189
// The low-order bit is the "untied" flag
1184-
if (!(gomp_flags & 1)) {
1190+
if (!(gomp_flags & KMP_GOMP_TASK_UNTIED_FLAG)) {
11851191
input_flags->tiedness = 1;
11861192
}
11871193
// The second low-order bit is the "final" flag
1188-
if (gomp_flags & 2) {
1194+
if (gomp_flags & KMP_GOMP_TASK_FINAL_FLAG) {
11891195
input_flags->final = 1;
11901196
}
11911197
input_flags->native = 1;
@@ -1223,7 +1229,7 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
12231229
#endif
12241230

12251231
if (if_cond) {
1226-
if (gomp_flags & 8) {
1232+
if (gomp_flags & KMP_GOMP_TASK_DEPENDS_FLAG) {
12271233
KMP_ASSERT(depend);
12281234
kmp_gomp_depends_info_t gomp_depends(depend);
12291235
kmp_int32 ndeps = gomp_depends.get_num_deps();
@@ -1250,6 +1256,15 @@ void KMP_EXPAND_NAME(KMP_API_NAME_GOMP_TASK)(void (*func)(void *), void *data,
12501256
OMPT_STORE_RETURN_ADDRESS(gtid);
12511257
}
12521258
#endif
1259+
if (gomp_flags & KMP_GOMP_TASK_DEPENDS_FLAG) {
1260+
KMP_ASSERT(depend);
1261+
kmp_gomp_depends_info_t gomp_depends(depend);
1262+
kmp_int32 ndeps = gomp_depends.get_num_deps();
1263+
kmp_depend_info_t dep_list[ndeps];
1264+
for (kmp_int32 i = 0; i < ndeps; i++)
1265+
dep_list[i] = gomp_depends.get_kmp_depend(i);
1266+
__kmpc_omp_wait_deps(&loc, gtid, ndeps, dep_list, 0, NULL);
1267+
}
12531268

12541269
__kmpc_omp_task_begin_if0(&loc, gtid, task);
12551270
func(data);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %libomp-compile-and-run
2+
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <omp.h>
6+
#include "omp_my_sleep.h"
7+
8+
int a = 0;
9+
10+
void task1() {
11+
my_sleep(0.5);
12+
a = 10;
13+
}
14+
15+
void task2() {
16+
a++;
17+
}
18+
19+
int main(int argc, char** argv)
20+
{
21+
#pragma omp parallel shared(argc) num_threads(2)
22+
{
23+
#pragma omp single
24+
{
25+
#pragma omp task depend(out: a)
26+
task1();
27+
28+
#pragma omp task if(0) depend(inout: a)
29+
task2();
30+
}
31+
}
32+
if (a != 11) {
33+
fprintf(stderr, "fail: expected 11, but a is %d\n", a);
34+
exit(1);
35+
} else {
36+
printf("pass\n");
37+
}
38+
return 0;
39+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// RUN: %libomp-compile-and-run
2+
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <omp.h>
6+
#include "omp_my_sleep.h"
7+
8+
int a = 0, b = 0;
9+
int task_grabbed = 0, task_can_proceed = 0;
10+
int task2_grabbed = 0, task2_can_proceed = 0;
11+
12+
static void wait_on_flag(int *flag) {
13+
int flag_value;
14+
int timelimit = 30;
15+
int secs = 0;
16+
do {
17+
#pragma omp atomic read
18+
flag_value = *flag;
19+
my_sleep(1.0);
20+
secs++;
21+
if (secs == timelimit) {
22+
fprintf(stderr, "error: timeout in wait_on_flag()\n");
23+
exit(EXIT_FAILURE);
24+
}
25+
} while (flag_value == 0);
26+
}
27+
28+
static void signal_flag(int *flag) {
29+
#pragma omp atomic
30+
(*flag)++;
31+
}
32+
33+
int main(int argc, char** argv) {
34+
35+
// Ensure two threads are running
36+
int num_threads = omp_get_max_threads();
37+
if (num_threads < 2)
38+
omp_set_num_threads(2);
39+
40+
#pragma omp parallel shared(a)
41+
{
42+
int a_value;
43+
// Let us be extra safe here
44+
if (omp_get_num_threads() > 1) {
45+
#pragma omp single nowait
46+
{
47+
// Schedule independent child task that
48+
// waits to be flagged after sebsequent taskwait depend()
49+
#pragma omp task
50+
{
51+
signal_flag(&task_grabbed);
52+
wait_on_flag(&task_can_proceed);
53+
}
54+
// Let another worker thread grab the task to execute
55+
wait_on_flag(&task_grabbed);
56+
// This should be ignored since the task above has
57+
// no dependency information
58+
#pragma omp task if(0) depend(inout: a)
59+
{}
60+
// Signal the independent task to proceed
61+
signal_flag(&task_can_proceed);
62+
63+
// Schedule child task with dependencies that taskwait does
64+
// not care about
65+
#pragma omp task depend(inout: b)
66+
{
67+
signal_flag(&task2_grabbed);
68+
wait_on_flag(&task2_can_proceed);
69+
#pragma omp atomic
70+
b++;
71+
}
72+
// Let another worker thread grab the task to execute
73+
wait_on_flag(&task2_grabbed);
74+
// This should be ignored since the task above has
75+
// dependency information on b instead of a
76+
#pragma omp task if(0) depend(inout: a)
77+
{}
78+
// Signal the task to proceed
79+
signal_flag(&task2_can_proceed);
80+
81+
// Generate one child task for taskwait
82+
#pragma omp task shared(a) depend(inout: a)
83+
{
84+
my_sleep(1.0);
85+
#pragma omp atomic
86+
a++;
87+
}
88+
#pragma omp task if(0) depend(inout: a)
89+
{}
90+
91+
#pragma omp atomic read
92+
a_value = a;
93+
94+
if (a_value != 1) {
95+
fprintf(stderr, "error: dependent task was not executed before "
96+
"taskwait finished\n");
97+
exit(EXIT_FAILURE);
98+
}
99+
} // #pragma omp single
100+
} // if (num_threads > 1)
101+
} // #pragma omp parallel
102+
103+
return EXIT_SUCCESS;
104+
}

0 commit comments

Comments
 (0)