xref: /llvm-project/openmp/runtime/test/tasking/bug_taskwait_detach.cpp (revision af6511d730f18beb9053c0120c45abef031344e9)
1 // RUN: %libomp-cxx-compile-and-run
2 
3 #include <omp.h>
4 
5 #include <chrono>
6 #include <cstdint>
7 #include <iostream>
8 #include <thread>
9 
10 // detached
11 #define PTASK_FLAG_DETACHABLE 0x40
12 
13 // OpenMP RTL interfaces
14 using kmp_int32 = int32_t;
15 
16 typedef struct ID {
17   int reserved_1;
18   int flags;
19   int reserved_2;
20   int reserved_3;
21   char *psource;
22 } id;
23 
24 // Compiler-generated code (emulation)
25 typedef struct ident {
26   void *dummy; // not used in the library
27 } ident_t;
28 
29 typedef enum kmp_event_type_t {
30   KMP_EVENT_UNINITIALIZED = 0,
31   KMP_EVENT_ALLOW_COMPLETION = 1
32 } kmp_event_type_t;
33 
34 typedef struct {
35   kmp_event_type_t type;
36   union {
37     void *task;
38   } ed;
39 } kmp_event_t;
40 
41 typedef struct shar { // shareds used in the task
42 } * pshareds;
43 
44 typedef struct task {
45   pshareds shareds;
46   int (*routine)(int, struct task *);
47   int part_id;
48   // void *destructor_thunk; // optional, needs flag setting if provided
49   // int priority; // optional, needs flag setting if provided
50   // ------------------------------
51   // privates used in the task:
52   omp_event_handle_t evt;
53 } * ptask, kmp_task_t;
54 
55 typedef int (*task_entry_t)(int, ptask);
56 
57 #ifdef __cplusplus
58 extern "C" {
59 #endif
60 extern int __kmpc_global_thread_num(void *id_ref);
61 extern int **__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz,
62                                    size_t shar, task_entry_t rtn);
63 extern kmp_int32 __kmpc_omp_task(ident_t *loc_ref, kmp_int32 gtid,
64                                  kmp_task_t *new_task);
65 extern omp_event_handle_t __kmpc_task_allow_completion_event(ident_t *loc_ref,
66                                                              int gtid,
67                                                              kmp_task_t *task);
68 #ifdef __cplusplus
69 }
70 #endif
71 
72 int volatile checker;
73 
target(ptask task)74 void target(ptask task) {
75   std::this_thread::sleep_for(std::chrono::seconds(3));
76   checker = 1;
77   omp_fulfill_event(task->evt);
78 }
79 
80 // User's code
task_entry(int gtid,ptask task)81 int task_entry(int gtid, ptask task) {
82   std::thread t(target, task);
83   t.detach();
84   return 0;
85 }
86 
main(int argc,char * argv[])87 int main(int argc, char *argv[]) {
88   int gtid = __kmpc_global_thread_num(nullptr);
89   checker = 0;
90 
91   /*
92     #pragma omp task detach(evt)
93     {}
94   */
95   std::cout << "detaching...\n";
96   ptask task = (ptask)__kmpc_omp_task_alloc(
97       nullptr, gtid, PTASK_FLAG_DETACHABLE, sizeof(struct task),
98       sizeof(struct shar), &task_entry);
99   omp_event_handle_t evt =
100       (omp_event_handle_t)__kmpc_task_allow_completion_event(nullptr, gtid,
101                                                              task);
102   task->evt = evt;
103 
104   __kmpc_omp_task(nullptr, gtid, task);
105 
106 #pragma omp taskwait
107 
108   // check results
109   if (checker == 1) {
110     std::cout << "PASS\n";
111     return 0;
112   }
113 
114   return 1;
115 }
116 
117 // CHECK: PASS
118