1// REQUIRES: ompx_taskgraph
2// RUN: %libomp-cxx-compile-and-run
3#include <iostream>
4#include <cassert>
5#define NT 20
6#define MULTIPLIER 100
7#define DECREMENT 5
8
9// Compiler-generated code (emulation)
10typedef struct ident {
11 void* dummy;
12} ident_t;
13
14int val;
15#ifdef __cplusplus
16extern "C" {
17 int __kmpc_global_thread_num(ident_t *);
18 int __kmpc_start_record_task(ident_t *, int, int, int);
19 void __kmpc_end_record_task(ident_t *, int, int , int);
20}
21#endif
22
23void sub() {
24 #pragma omp atomic
25 val -= DECREMENT;
26}
27
28void add() {
29 #pragma omp atomic
30 val += DECREMENT;
31}
32
33void mult() {
34 // no atomicity needed, can only be executed by 1 thread
35 // and no concurrency with other tasks possible
36 val *= MULTIPLIER;
37}
38
39int main() {
40 int num_tasks = 0;
41 int *x, *y;
42 #pragma omp parallel
43 #pragma omp single
44 for (int iter = 0; iter < NT; ++iter) {
45 int gtid = __kmpc_global_thread_num(nullptr);
46 int res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */0);
47 if (res) {
48 num_tasks++;
49 #pragma omp task depend(out:y)
50 add();
51 #pragma omp task depend(out:x)
52 sub();
53 #pragma omp task depend(in:x,y)
54 mult();
55 }
56 __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */0, /* tdg_id */0);
57 res = __kmpc_start_record_task(nullptr, gtid, /* kmp_tdg_flags */ 0, /* tdg_id */1);
58 if (res) {
59 num_tasks++;
60 #pragma omp task depend(out:y)
61 add();
62 #pragma omp task depend(out:x)
63 sub();
64 #pragma omp task depend(in:x,y)
65 mult();
66 }
67 __kmpc_end_record_task(nullptr, gtid, /* kmp_tdg_flags */0, /* tdg_id */1);
68 }
69
70 assert(num_tasks==2);
71 assert(val==0);
72
73 std::cout << "Passed" << std::endl;
74 return 0;
75}
76// CHECK: Passed
77

source code of openmp/runtime/test/tasking/omp_record_replay_multiTDGs.cpp