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