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 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 81 int task_entry(int gtid, ptask task) { 82 std::thread t(target, task); 83 t.detach(); 84 return 0; 85 } 86 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