LLVM OpenMP 20.0.0git
omp_task_depend_all.c
Go to the documentation of this file.
1// RUN--: %libarcher-compile-and-run | FileCheck %s --check-prefix=NOENV
2// RUN: %libarcher-compile && env ARCHER_OPTIONS="all_memory=1" \
3// RUN: %libarcher-run | FileCheck %s --check-prefix=ENV
4// REQUIRES: tsan
5
6// The runtime currently does not get dependency information from GCC.
7// UNSUPPORTED: gcc
8
9// Tests OMP 5.x task dependence "omp_all_memory",
10// emulates compiler codegen versions for new dep kind
11//
12// Task tree created:
13// task0 - task1 (in: i1, i2)
14// \
15// task2 (inoutset: i2), (in: i1)
16// /
17// task3 (omp_all_memory) via flag=0x80
18// /
19// task4 - task5 (in: i1, i2)
20// /
21// task6 (omp_all_memory) via addr=-1
22// /
23// task7 (omp_all_memory) via flag=0x80
24// /
25// task8 (in: i3)
26//
27
28#include <omp.h>
29#include <stdio.h>
30
31#ifdef _WIN32
32#include <windows.h>
33#define mysleep(n) Sleep(n)
34#else
35#include <unistd.h>
36#define mysleep(n) usleep((n)*1000)
37#endif
38
39// to check the # of concurrent tasks (must be 1 for MTX, <3 for other kinds)
40static int checker = 0;
41static int err = 0;
42#ifndef DELAY
43#define DELAY 100
44#endif
45
46// ---------------------------------------------------------------------------
47// internal data to emulate compiler codegen
48typedef struct DEP {
49 size_t addr;
50 size_t len;
51 unsigned char flags;
53#define DEP_ALL_MEM 0x80
54typedef struct task {
55 void **shareds;
56 void *entry;
57 int part_id;
58 void *destr_thunk;
59 int priority;
60 long long device_id;
61 int f_priv;
63#define TIED 1
64typedef int (*entry_t)(int, task_t *);
65typedef struct ID {
66 int reserved_1;
67 int flags;
68 int reserved_2;
69 int reserved_3;
70 char *psource;
72// thunk routine for tasks with ALL dependency
73int thunk_m(int gtid, task_t *ptask) {
74 int lcheck, th;
75#pragma omp atomic capture
76 lcheck = ++checker;
77 th = omp_get_thread_num();
78 printf("task m_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);
79 if (lcheck != 1) { // no more than 1 task at a time
80 err++;
81 printf("Error m1, checker %d != 1\n", lcheck);
82 }
84#pragma omp atomic read
85 lcheck = checker; // must still be equal to 1
86 if (lcheck != 1) {
87 err++;
88 printf("Error m2, checker %d != 1\n", lcheck);
89 }
90#pragma omp atomic
91 --checker;
92 return 0;
93}
94// thunk routine for tasks with inoutset dependency
95int thunk_s(int gtid, task_t *ptask) {
96 int lcheck, th;
97#pragma omp atomic capture
98 lcheck = ++checker; // 1
99 th = omp_get_thread_num();
100 printf("task 2_%d, th %d, checker %d\n", ptask->f_priv, th, lcheck);
101 if (lcheck != 1) { // no more than 1 task at a time
102 err++;
103 printf("Error s1, checker %d != 1\n", lcheck);
104 }
105 mysleep(DELAY);
106#pragma omp atomic read
107 lcheck = checker; // must still be equal to 1
108 if (lcheck != 1) {
109 err++;
110 printf("Error s2, checker %d != 1\n", lcheck);
111 }
112#pragma omp atomic
113 --checker;
114 return 0;
115}
116
117#ifdef __cplusplus
118extern "C" {
119#endif
121task_t *__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,
122 size_t shar, entry_t rtn);
123int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps,
124 dep *dep_lst, int nd_noalias, dep *noalias_lst);
125static id loc = {0, 2, 0, 0, ";file;func;0;0;;"};
126#ifdef __cplusplus
127} // extern "C"
128#endif
129// End of internal data
130// ---------------------------------------------------------------------------
131
132int main() {
133 char *ompx_all_memory = (void *)0xffffffffffffffff;
134 int i1, i2, i3;
137#pragma omp parallel
138 {
139#pragma omp single nowait
140 {
141 dep sdep[2];
142 task_t *ptr;
143 int gtid = __kmpc_global_thread_num(&loc);
144 int t = omp_get_thread_num();
145#pragma omp task depend(in : i1, i2)
146 { // task 0
147 int lcheck, th;
148#pragma omp atomic capture
149 lcheck = ++checker; // 1 or 2
150 th = omp_get_thread_num();
151 printf("task 0_%d, th %d, checker %d\n", t, th, lcheck);
152 if (lcheck > 2 || lcheck < 1) {
153 err++; // no more than 2 tasks concurrently
154 printf("Error1, checker %d, not 1 or 2\n", lcheck);
155 }
156 mysleep(DELAY);
157#pragma omp atomic read
158 lcheck = checker; // 1 or 2
159 if (lcheck > 2 || lcheck < 1) {
160#pragma omp atomic
161 err++;
162 printf("Error2, checker %d, not 1 or 2\n", lcheck);
163 }
164#pragma omp atomic
165 --checker;
166 }
167#pragma omp task depend(in : i1, i2)
168 { // task 1
169 int lcheck, th;
170#pragma omp atomic capture
171 lcheck = ++checker; // 1 or 2
172 th = omp_get_thread_num();
173 printf("task 1_%d, th %d, checker %d\n", t, th, lcheck);
174 if (lcheck > 2 || lcheck < 1) {
175 err++; // no more than 2 tasks concurrently
176 printf("Error3, checker %d, not 1 or 2\n", lcheck);
177 }
178 mysleep(DELAY);
179#pragma omp atomic read
180 lcheck = checker; // 1 or 2
181 if (lcheck > 2 || lcheck < 1) {
182 err++;
183 printf("Error4, checker %d, not 1 or 2\n", lcheck);
184 }
185#pragma omp atomic
186 --checker;
187 }
188 // compiler codegen start
189 // task2
190 ptr = __kmpc_omp_task_alloc(&loc, gtid, TIED, sizeof(task_t), 0, thunk_s);
191 sdep[0].addr = (size_t)&i1;
192 sdep[0].len = 0; // not used
193 sdep[0].flags = 1; // IN
194 sdep[1].addr = (size_t)&i2;
195 sdep[1].len = 0; // not used
196 sdep[1].flags = 8; // INOUTSET
197 ptr->f_priv = t + 10; // init single first-private variable
198 __kmpc_omp_task_with_deps(&loc, gtid, ptr, 2, sdep, 0, 0);
199
200// task3
201#pragma omp task depend(in : i1) depend(inout : ompx_all_memory[0])
202 {
203 int lcheck, th;
204#pragma omp atomic capture
205 lcheck = ++checker;
206 th = omp_get_thread_num();
207 printf("task 3_%d, th %d, checker %d\n", t, th, lcheck);
208 if (lcheck != 1) { // no more than 1 task at a time
209 err++;
210 printf("Error m1, checker %d != 1\n", lcheck);
211 }
212 mysleep(DELAY);
213#pragma omp atomic read
214 lcheck = checker; // must still be equal to 1
215 if (lcheck != 1) {
216 err++;
217 printf("Error m2, checker %d != 1\n", lcheck);
218 }
219#pragma omp atomic
220 --checker;
221 }
222 // compiler codegen end
223#pragma omp task depend(in : i1, i2)
224 { // task 4
225 int lcheck, th;
226#pragma omp atomic capture
227 lcheck = ++checker; // 1 or 2
228 th = omp_get_thread_num();
229 printf("task 4_%d, th %d, checker %d\n", t, th, lcheck);
230 if (lcheck > 2 || lcheck < 1) {
231 err++; // no more than 2 tasks concurrently
232 printf("Error5, checker %d, not 1 or 2\n", lcheck);
233 }
234 mysleep(DELAY);
235#pragma omp atomic read
236 lcheck = checker; // 1 or 2
237 if (lcheck > 2 || lcheck < 1) {
238 err++;
239 printf("Error6, checker %d, not 1 or 2\n", lcheck);
240 }
241#pragma omp atomic
242 --checker;
243 }
244#pragma omp task depend(in : i1, i2)
245 { // task 5
246 int lcheck, th;
247#pragma omp atomic capture
248 lcheck = ++checker; // 1 or 2
249 th = omp_get_thread_num();
250 printf("task 5_%d, th %d, checker %d\n", t, th, lcheck);
251 if (lcheck > 2 || lcheck < 1) {
252 err++; // no more than 2 tasks concurrently
253 printf("Error7, checker %d, not 1 or 2\n", lcheck);
254 }
255 mysleep(DELAY);
256#pragma omp atomic read
257 lcheck = checker; // 1 or 2
258 if (lcheck > 2 || lcheck < 1) {
259 err++;
260 printf("Error8, checker %d, not 1 or 2\n", lcheck);
261 }
262#pragma omp atomic
263 --checker;
264 }
265// task6
266#pragma omp task depend(inout : ompx_all_memory[0])
267 {
268 int lcheck, th;
269#pragma omp atomic capture
270 lcheck = ++checker;
271 th = omp_get_thread_num();
272 printf("task 6_%d, th %d, checker %d\n", t, th, lcheck);
273 if (lcheck != 1) { // no more than 1 task at a time
274 err++;
275 printf("Error m1, checker %d != 1\n", lcheck);
276 }
277 mysleep(DELAY);
278#pragma omp atomic read
279 lcheck = checker; // must still be equal to 1
280 if (lcheck != 1) {
281 err++;
282 printf("Error m2, checker %d != 1\n", lcheck);
283 }
284#pragma omp atomic
285 --checker;
286 }
287// task7
288#pragma omp task depend(inout : ompx_all_memory[0]) depend(mutexinoutset : i3)
289 {
290 int lcheck, th;
291#pragma omp atomic capture
292 lcheck = ++checker;
293 th = omp_get_thread_num();
294 printf("task 7_%d, th %d, checker %d\n", t, th, lcheck);
295 if (lcheck != 1) { // no more than 1 task at a time
296 err++;
297 printf("Error m1, checker %d != 1\n", lcheck);
298 }
299 mysleep(DELAY);
300#pragma omp atomic read
301 lcheck = checker; // must still be equal to 1
302 if (lcheck != 1) {
303 err++;
304 printf("Error m2, checker %d != 1\n", lcheck);
305 }
306#pragma omp atomic
307 --checker;
308 }
309#pragma omp task depend(in : i3)
310 { // task 8
311 int lcheck, th;
312#pragma omp atomic capture
313 lcheck = ++checker; // 1
314 th = omp_get_thread_num();
315 printf("task 8_%d, th %d, checker %d\n", t, th, lcheck);
316 if (lcheck != 1) {
317 err++;
318 printf("Error9, checker %d, != 1\n", lcheck);
319 }
320 mysleep(DELAY);
321#pragma omp atomic read
322 lcheck = checker;
323 if (lcheck != 1) {
324 err++;
325 printf("Error10, checker %d, != 1\n", lcheck);
326 }
327#pragma omp atomic
328 --checker;
329 }
330 } // single
331 } // parallel
332 if (err == 0 && checker == 0) {
333 printf("passed\n");
334 return 0;
335 } else {
336 printf("failed, err = %d, checker = %d\n", err, checker);
337 return 1;
338 }
339}
340
341// NOENV-NOT: ThreadSanitizer: data race
342// NOENV-NOT: ThreadSanitizer: reported
343// NOENV: omp_all_memory
344// NOENV-NOT: ThreadSanitizer: data race
345// NOENV-NOT: ThreadSanitizer: reported
346// NOENV: passed
347
348// ENV-NOT: ThreadSanitizer: data race
349// ENV-NOT: ThreadSanitizer: reported
350// ENV: passed
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function void size_t int ITT_FORMAT d __itt_heap_function void ITT_FORMAT p __itt_heap_function void void size_t int ITT_FORMAT d no args no args unsigned int ITT_FORMAT u const __itt_domain __itt_id ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain __itt_id ITT_FORMAT p const __itt_domain __itt_id __itt_timestamp __itt_timestamp ITT_FORMAT lu const __itt_domain __itt_id __itt_id __itt_string_handle ITT_FORMAT p const __itt_domain ITT_FORMAT p const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_string_handle unsigned long long ITT_FORMAT lu const __itt_domain __itt_id __itt_string_handle __itt_metadata_type size_t void ITT_FORMAT p const __itt_domain __itt_id __itt_string_handle const wchar_t size_t ITT_FORMAT lu const __itt_domain __itt_id __itt_relation __itt_id ITT_FORMAT p const wchar_t int ITT_FORMAT __itt_group_mark d int
#define omp_set_num_threads
Definition: kmp_stub.cpp:34
#define omp_set_dynamic
Definition: kmp_stub.cpp:35
#define mysleep(n)
struct ID id
int thunk_s(int gtid, task_t *ptask)
struct DEP dep
#define DELAY
static int err
int(* entry_t)(int, task_t *)
int thunk_m(int gtid, task_t *ptask)
static id loc
int __kmpc_omp_task_with_deps(id *loc, int gtid, task_t *task, int ndeps, dep *dep_lst, int nd_noalias, dep *noalias_lst)
task_t * __kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz, size_t shar, entry_t rtn)
static int checker
int __kmpc_global_thread_num(id *)
#define TIED
struct task task_t
int main()
size_t len
unsigned char flags
size_t addr
int reserved_2
char * psource
int reserved_3
int reserved_1
void * entry
void ** shareds
void * destr_thunk
long long device_id