diff --git a/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/runtime/src/kmp_tasking.cpp @@ -1271,7 +1271,7 @@ } } - if (flags->proxy == TASK_PROXY && + if ((flags->proxy == TASK_PROXY || flags->detachable == TASK_DETACHABLE) && task_team->tt.tt_found_proxy_tasks == FALSE) TCW_4(task_team->tt.tt_found_proxy_tasks, TRUE); if (flags->hidden_helper && diff --git a/openmp/runtime/test/tasking/bug_taskwait_detach.c b/openmp/runtime/test/tasking/bug_taskwait_detach.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/tasking/bug_taskwait_detach.c @@ -0,0 +1,115 @@ +// RUN: %libomp-compile-and-run + +#include +#include +#include +#include + +// detached +#define PTASK_FLAG_DETACHABLE 0x40 + +// OpenMP RTL interfaces +typedef long long kmp_int64; + +typedef struct ID { + int reserved_1; + int flags; + int reserved_2; + int reserved_3; + char *psource; +} id; + +// Compiler-generated code (emulation) +typedef struct ident { + void *dummy; // not used in the library +} ident_t; + +typedef enum kmp_event_type_t { + KMP_EVENT_UNINITIALIZED = 0, + KMP_EVENT_ALLOW_COMPLETION = 1 +} kmp_event_type_t; + +typedef struct { + kmp_event_type_t type; + union { + void *task; + } ed; +} kmp_event_t; + +typedef struct shar { // shareds used in the task +} * pshareds; + +typedef struct task { + pshareds shareds; + int (*routine)(int, struct task *); + int part_id; + // void *destructor_thunk; // optional, needs flag setting if provided + // int priority; // optional, needs flag setting if provided + // ------------------------------ + // privates used in the task: + omp_event_handle_t evt; +} * ptask, kmp_task_t; + +typedef int (*task_entry_t)(int, ptask); + +#ifdef __cplusplus +extern "C" { +#endif +extern int __kmpc_global_thread_num(void *id_ref); +extern int **__kmpc_omp_task_alloc(id *loc, int gtid, int flags, size_t sz, + size_t shar, task_entry_t rtn); +extern int __kmpc_omp_task(id *loc, kmp_int64 gtid, kmp_task_t *task); +extern omp_event_handle_t __kmpc_task_allow_completion_event(ident_t *loc_ref, + int gtid, + kmp_task_t *task); +#ifdef __cplusplus +} +#endif + +int volatile checker; + +void *target(void *task) { + sleep(3); + checker = 1; + omp_fulfill_event(((ptask)task)->evt); + return NULL; +} + +pthread_t target_thread; + +// User's code +int task_entry(int gtid, ptask task) { + pthread_create(&target_thread, NULL, &target, task); + return 0; +} + +int main() { + int gtid = __kmpc_global_thread_num(NULL); + ptask task; + checker = 0; + omp_event_handle_t evt; + /* + #pragma omp task detach(evt) + {} + */ + printf("detaching...\n"); + task = (ptask)__kmpc_omp_task_alloc(NULL, gtid, PTASK_FLAG_DETACHABLE, + sizeof(struct task), sizeof(struct shar), + &task_entry); + evt = + (omp_event_handle_t)__kmpc_task_allow_completion_event(NULL, gtid, task); + task->evt = evt; + + __kmpc_omp_task(NULL, gtid, task); +#pragma omp taskwait + + // check results + if (checker == 1) { + printf("PASS\n"); + return 0; + } + + return 1; +} + +// CHECK: PASS