Index: openmp/trunk/runtime/src/dllexports =================================================================== --- openmp/trunk/runtime/src/dllexports +++ openmp/trunk/runtime/src/dllexports @@ -408,7 +408,7 @@ __kmpc_pause_resource 273 __kmpc_task_reduction_modifier_init 274 __kmpc_task_reduction_modifier_fini 275 - # __kmpc_task_allow_completion_event 276 + __kmpc_task_allow_completion_event 276 __kmpc_taskred_init 277 __kmpc_taskred_modifier_init 278 %endif @@ -572,6 +572,7 @@ omp_pause_resource 756 omp_pause_resource_all 757 omp_get_supported_active_levels 758 + omp_fulfill_event 759 omp_null_allocator DATA omp_default_mem_alloc DATA Index: openmp/trunk/runtime/src/include/50/omp.h.var =================================================================== --- openmp/trunk/runtime/src/include/50/omp.h.var +++ openmp/trunk/runtime/src/include/50/omp.h.var @@ -334,6 +334,15 @@ extern void __KAI_KMPC_CONVENTION omp_display_affinity(char const *); extern size_t __KAI_KMPC_CONVENTION omp_capture_affinity(char *, size_t, char const *); + /* OpenMP 5.0 events */ +# if defined(_WIN32) + // On Windows cl and icl do not support 64-bit enum, let's use integer then. + typedef omp_uintptr_t omp_event_handle_t; +# else + typedef enum omp_event_handle_t { KMP_EVENT_MAX_HANDLE = UINTPTR_MAX } omp_event_handle_t; +# endif + extern void __KAI_KMPC_CONVENTION omp_fulfill_event ( omp_event_handle_t event ); + /* OpenMP 5.0 Pause Resources */ typedef enum omp_pause_resource_t { omp_pause_resume = 0, Index: openmp/trunk/runtime/src/include/50/omp_lib.h.var =================================================================== --- openmp/trunk/runtime/src/include/50/omp_lib.h.var +++ openmp/trunk/runtime/src/include/50/omp_lib.h.var @@ -50,6 +50,8 @@ parameter(omp_pause_resource_kind=omp_integer_kind) integer omp_depend_kind parameter(omp_depend_kind=int_ptr_kind()) + integer omp_event_handle_kind + parameter(omp_event_handle_kind=int_ptr_kind()) integer(kind=omp_integer_kind)openmp_version parameter(openmp_version=@LIBOMP_OMP_YEAR_MONTH@) @@ -442,6 +444,11 @@ integer (kind=omp_integer_kind) omp_get_supported_active_levels end function omp_get_supported_active_levels + subroutine omp_fulfill_event(event) bind(c) + import + integer (kind=omp_event_handle_kind), value :: event + end subroutine omp_fulfill_event + subroutine omp_init_lock(svar) bind(c) !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock @@ -778,6 +785,7 @@ !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_pause_resource !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_pause_resource_all !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_supported_active_levels +!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_fulfill_event !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_teams !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_team_num !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_init_lock @@ -860,6 +868,7 @@ !$omp declare target(omp_pause_resource ) !$omp declare target(omp_pause_resource_all ) !$omp declare target(omp_get_supported_active_levels ) +!$omp declare target(omp_fulfill_event) !$omp declare target(omp_get_num_teams ) !$omp declare target(omp_get_team_num ) !$omp declare target(omp_init_lock ) Index: openmp/trunk/runtime/src/include/50/omp_lib.f.var =================================================================== --- openmp/trunk/runtime/src/include/50/omp_lib.f.var +++ openmp/trunk/runtime/src/include/50/omp_lib.f.var @@ -45,6 +45,7 @@ integer, parameter :: omp_pause_resource_kind = omp_integer_kind integer, parameter :: omp_depend_kind = int_ptr_kind() + integer, parameter :: omp_event_handle_kind = int_ptr_kind() end module omp_lib_kinds @@ -351,6 +352,11 @@ integer (kind=omp_integer_kind) omp_get_supported_active_levels end function omp_get_supported_active_levels + subroutine omp_fulfill_event(event) + use omp_lib_kinds + integer (kind=omp_event_handle_kind) event + end subroutine omp_fulfill_event + subroutine omp_init_lock(svar) !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock @@ -705,6 +711,7 @@ !dec$ attributes alias:'OMP_PAUSE_RESOURCE' :: omp_pause_resource !dec$ attributes alias:'OMP_PAUSE_RESOURCE_ALL' :: omp_pause_resource_all !dec$ attributes alias:'OMP_GET_SUPPORTED_ACTIVE_LEVELS' :: omp_get_supported_active_levels +!dec$ attributes alias:'OMP_FULFILL_EVENT' :: omp_fulfill_event !dec$ attributes alias:'OMP_CONTROL_TOOL' :: omp_control_tool !dec$ attributes alias:'OMP_SET_AFFINITY_FORMAT' :: omp_set_affinity_format @@ -796,6 +803,7 @@ !dec$ attributes alias:'_OMP_PAUSE_RESOURCE' :: omp_pause_resource !dec$ attributes alias:'_OMP_PAUSE_RESOURCE_ALL' :: omp_pause_resource_all !dec$ attributes alias:'_OMP_GET_SUPPORTED_ACTIVE_LEVELS' :: omp_get_supported_active_levels +!dec$ attributes alias:'_OMP_FULFILL_EVENT' :: omp_fulfill_event !dec$ attributes alias:'_OMP_CONTROL_TOOL' :: omp_control_tool !dec$ attributes alias:'_OMP_SET_AFFINITY_FORMAT' :: omp_set_affinity_format @@ -890,6 +898,7 @@ !dec$ attributes alias:'omp_pause_resource_' :: omp_pause_resource !dec$ attributes alias:'omp_pause_resource_all_' :: omp_pause_resource_all !dec$ attributes alias:'omp_get_supported_active_levels_' :: omp_get_supported_active_levels +!dec$ attributes alias:'omp_fulfill_event_' :: omp_fulfill_event !dec$ attributes alias:'omp_set_affinity_format_' :: omp_set_affinity_format !dec$ attributes alias:'omp_get_affinity_format_' :: omp_get_affinity_format @@ -983,6 +992,7 @@ !dec$ attributes alias:'_omp_pause_resource_' :: omp_pause_resource !dec$ attributes alias:'_omp_pause_resource_all_' :: omp_pause_resource_all !dec$ attributes alias:'_omp_get_supported_active_levels_' :: omp_get_supported_active_levels +!dec$ attributes alias:'_omp_fulfill_event_' :: omp_fulfill_event !dec$ attributes alias:'_omp_init_lock_'::omp_init_lock !dec$ attributes alias:'_omp_init_lock_with_hint_'::omp_init_lock_with_hint Index: openmp/trunk/runtime/src/include/50/omp_lib.f90.var =================================================================== --- openmp/trunk/runtime/src/include/50/omp_lib.f90.var +++ openmp/trunk/runtime/src/include/50/omp_lib.f90.var @@ -42,6 +42,7 @@ integer, parameter :: omp_pause_resource_kind = omp_integer_kind integer, parameter :: omp_depend_kind = c_intptr_t + integer, parameter :: omp_event_handle_kind = c_intptr_t end module omp_lib_kinds @@ -366,6 +367,11 @@ integer (kind=omp_integer_kind) omp_get_supported_active_levels end function omp_get_supported_active_levels + subroutine omp_fulfill_event(event) bind(c) + use omp_lib_kinds + integer (kind=omp_event_handle_kind), value :: event + end subroutine omp_fulfill_event + subroutine omp_init_lock(svar) bind(c) !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock Index: openmp/trunk/runtime/src/kmp.h =================================================================== --- openmp/trunk/runtime/src/kmp.h +++ openmp/trunk/runtime/src/kmp.h @@ -48,6 +48,8 @@ #define TASK_IMPLICIT 0 #define TASK_PROXY 1 #define TASK_FULL 0 +#define TASK_DETACHABLE 1 +#define TASK_UNDETACHABLE 0 #define KMP_CANCEL_THREADS #define KMP_THREAD_ATTR @@ -2269,6 +2271,19 @@ kmp_int32 reserved : 30; } flags; } kmp_task_affinity_info_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; + kmp_tas_lock_t lock; + union { + kmp_task_t *task; + } ed; +} kmp_event_t; #endif #endif @@ -2304,7 +2319,8 @@ context of the RTL) */ unsigned priority_specified : 1; /* set if the compiler provides priority setting for the task */ - unsigned reserved : 10; /* reserved for compiler use */ + unsigned detachable : 1; /* 1 == can detach */ + unsigned reserved : 9; /* reserved for compiler use */ #else unsigned reserved : 12; /* reserved for compiler use */ #endif @@ -2372,6 +2388,9 @@ // GOMP sends in a copy function for copy constructors void (*td_copy_func)(void *, void *); #endif +#if OMP_50_ENABLED + kmp_event_t td_allow_completion_event; +#endif #if OMPT_SUPPORT ompt_task_info_t ompt_task_info; #endif @@ -3642,6 +3661,14 @@ int set_curr_task); extern void __kmp_finish_implicit_task(kmp_info_t *this_thr); extern void __kmp_free_implicit_task(kmp_info_t *this_thr); + +#ifdef OMP_50_ENABLED +extern kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, + int gtid, + kmp_task_t *task); +extern void __kmp_fulfill_event(kmp_event_t *event); +#endif + int __kmp_execute_tasks_32(kmp_info_t *thread, kmp_int32 gtid, kmp_flag_32 *flag, int final_spin, int *thread_finished, Index: openmp/trunk/runtime/src/kmp_ftn_entry.h =================================================================== --- openmp/trunk/runtime/src/kmp_ftn_entry.h +++ openmp/trunk/runtime/src/kmp_ftn_entry.h @@ -1387,6 +1387,12 @@ #endif } +void FTN_STDCALL FTN_FULFILL_EVENT(kmp_event_t *event) { +#ifndef KMP_STUB + __kmp_fulfill_event(event); +#endif +} + #endif // OMP_50_ENABLED // GCC compatibility (versioned symbols) @@ -1493,6 +1499,7 @@ // KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE, 50, "OMP_5.0"); // KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE_ALL, 50, "OMP_5.0"); // KMP_VERSION_SYMBOL(FTN_GET_SUPPORTED_ACTIVE_LEVELS, 50, "OMP_5.0"); +// KMP_VERSION_SYMBOL(FTN_FULFILL_EVENT, 50, "OMP_5.0"); #endif #endif // KMP_USE_VERSION_SYMBOLS Index: openmp/trunk/runtime/src/kmp_ftn_os.h =================================================================== --- openmp/trunk/runtime/src/kmp_ftn_os.h +++ openmp/trunk/runtime/src/kmp_ftn_os.h @@ -144,6 +144,7 @@ #define FTN_PAUSE_RESOURCE omp_pause_resource #define FTN_PAUSE_RESOURCE_ALL omp_pause_resource_all #define FTN_GET_SUPPORTED_ACTIVE_LEVELS omp_get_supported_active_levels +#define FTN_FULFILL_EVENT omp_fulfill_event #endif #endif /* KMP_FTN_PLAIN */ @@ -278,6 +279,7 @@ #define FTN_PAUSE_RESOURCE omp_pause_resource_ #define FTN_PAUSE_RESOURCE_ALL omp_pause_resource_all_ #define FTN_GET_SUPPORTED_ACTIVE_LEVELS omp_get_supported_active_levels_ +#define FTN_FULFILL_EVENT omp_fulfill_event_ #endif #endif /* KMP_FTN_APPEND */ @@ -410,6 +412,7 @@ #define FTN_PAUSE_RESOURCE OMP_PAUSE_RESOURCE #define FTN_PAUSE_RESOURCE_ALL OMP_PAUSE_RESOURCE_ALL #define FTN_GET_SUPPORTED_ACTIVE_LEVELS OMP_GET_SUPPORTED_ACTIVE_LEVELS +#define FTN_FULFILL_EVENT OMP_FULFILL_EVENT #endif #endif /* KMP_FTN_UPPER */ @@ -544,6 +547,7 @@ #define FTN_PAUSE_RESOURCE OMP_PAUSE_RESOURCE_ #define FTN_PAUSE_RESOURCE_ALL OMP_PAUSE_RESOURCE_ALL_ #define FTN_GET_SUPPORTED_ACTIVE_LEVELS OMP_GET_SUPPORTED_ACTIVE_LEVELS_ +#define FTN_FULFILL_EVENT OMP_FULFILL_EVENT_ #endif #endif /* KMP_FTN_UAPPEND */ Index: openmp/trunk/runtime/src/kmp_tasking.cpp =================================================================== --- openmp/trunk/runtime/src/kmp_tasking.cpp +++ openmp/trunk/runtime/src/kmp_tasking.cpp @@ -874,28 +874,47 @@ } KMP_DEBUG_ASSERT(taskdata->td_flags.complete == 0); - taskdata->td_flags.complete = 1; // mark the task as completed + bool detach = false; +#if OMP_50_ENABLED + if (taskdata->td_flags.detachable == TASK_DETACHABLE) { + if (taskdata->td_allow_completion_event.type == + KMP_EVENT_ALLOW_COMPLETION) { + // event hasn't been fulfilled yet. Try to detach task. + __kmp_acquire_tas_lock(&taskdata->td_allow_completion_event.lock, gtid); + if (taskdata->td_allow_completion_event.type == + KMP_EVENT_ALLOW_COMPLETION) { + taskdata->td_flags.proxy = TASK_PROXY; // proxify! + detach = true; + } + __kmp_release_tas_lock(&taskdata->td_allow_completion_event.lock, gtid); + } + } +#endif KMP_DEBUG_ASSERT(taskdata->td_flags.started == 1); KMP_DEBUG_ASSERT(taskdata->td_flags.freed == 0); - // Only need to keep track of count if team parallel and tasking not - // serialized - if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) { - // Predecrement simulated by "- 1" calculation - children = - KMP_ATOMIC_DEC(&taskdata->td_parent->td_incomplete_child_tasks) - 1; - KMP_DEBUG_ASSERT(children >= 0); + if (!detach) { + taskdata->td_flags.complete = 1; // mark the task as completed + + // Only need to keep track of count if team parallel and tasking not + // serialized + if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) { + // Predecrement simulated by "- 1" calculation + children = + KMP_ATOMIC_DEC(&taskdata->td_parent->td_incomplete_child_tasks) - 1; + KMP_DEBUG_ASSERT(children >= 0); #if OMP_40_ENABLED - if (taskdata->td_taskgroup) - KMP_ATOMIC_DEC(&taskdata->td_taskgroup->count); - __kmp_release_deps(gtid, taskdata); + if (taskdata->td_taskgroup) + KMP_ATOMIC_DEC(&taskdata->td_taskgroup->count); + __kmp_release_deps(gtid, taskdata); #if OMP_45_ENABLED - } else if (task_team && task_team->tt.tt_found_proxy_tasks) { - // if we found proxy tasks there could exist a dependency chain - // with the proxy task as origin - __kmp_release_deps(gtid, taskdata); + } else if (task_team && task_team->tt.tt_found_proxy_tasks) { + // if we found proxy tasks there could exist a dependency chain + // with the proxy task as origin + __kmp_release_deps(gtid, taskdata); #endif // OMP_45_ENABLED #endif // OMP_40_ENABLED + } } // td_flags.executing must be marked as 0 after __kmp_release_deps has been @@ -942,7 +961,8 @@ // johnmc: if an asynchronous inquiry peers into the runtime system // it doesn't see the freed task as the current task. thread->th.th_current_task = resumed_task; - __kmp_free_task_and_ancestors(gtid, taskdata, thread); + if (!detach) + __kmp_free_task_and_ancestors(gtid, taskdata, thread); // TODO: GEH - make sure root team implicit task is initialized properly. // KMP_DEBUG_ASSERT( resumed_task->td_flags.executing == 0 ); @@ -1069,6 +1089,9 @@ task->td_depnode = NULL; #endif task->td_last_tied = task; +#if OMP_50_ENABLED + task->td_allow_completion_event.type = KMP_EVENT_UNINITIALIZED; +#endif if (set_curr_task) { // only do this init first time thread is created KMP_ATOMIC_ST_REL(&task->td_incomplete_child_tasks, 0); @@ -1187,11 +1210,19 @@ KMP_CHECK_UPDATE(thread->th.th_task_team->tt.tt_untied_task_encountered, 1); } +#if OMP_50_ENABLED + // Detachable tasks are not proxy tasks yet but could be in the future. Doing + // the tasking setup + // when that happens is too late. + if (flags->proxy == TASK_PROXY || flags->detachable == TASK_DETACHABLE) { +#endif #if OMP_45_ENABLED - if (flags->proxy == TASK_PROXY) { - flags->tiedness = TASK_UNTIED; - flags->merged_if0 = 1; - + if (flags->proxy == TASK_PROXY) { + flags->tiedness = TASK_UNTIED; + flags->merged_if0 = 1; +#if OMP_50_ENABLED + } +#endif /* are we running in a sequential parallel or tskm_immediate_exec... we need tasking support enabled */ if ((thread->th.th_task_team) == NULL) { @@ -1295,6 +1326,9 @@ #endif // OMP_40_ENABLED #if OMP_45_ENABLED taskdata->td_flags.proxy = flags->proxy; +#if OMP_50_ENABLED + taskdata->td_flags.detachable = flags->detachable; +#endif taskdata->td_task_team = thread->th.th_task_team; taskdata->td_size_alloc = shareds_offset + sizeof_shareds; #endif @@ -1334,15 +1368,20 @@ taskdata->td_last_tied = NULL; // will be set when the task is scheduled else taskdata->td_last_tied = taskdata; - +#if OMP_50_ENABLED + taskdata->td_allow_completion_event.type = KMP_EVENT_UNINITIALIZED; +#endif #if OMPT_SUPPORT if (UNLIKELY(ompt_enabled.enabled)) __ompt_task_init(taskdata, gtid); #endif // Only need to keep track of child task counts if team parallel and tasking not -// serialized or if it is a proxy task +// serialized or if it is a proxy or detachable task #if OMP_45_ENABLED if (flags->proxy == TASK_PROXY || +#if OMP_50_ENABLED + flags->detachable == TASK_DETACHABLE || +#endif !(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) #else if (!(taskdata->td_flags.team_serial || taskdata->td_flags.tasking_ser)) @@ -1378,11 +1417,20 @@ // __kmp_task_alloc() sets up all other runtime flags #if OMP_45_ENABLED +#if OMP_50_ENABLED + KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s %s %s) " + "sizeof_task=%ld sizeof_shared=%ld entry=%p\n", + gtid, loc_ref, input_flags->tiedness ? "tied " : "untied", + input_flags->proxy ? "proxy" : "", + input_flags->detachable ? "detachable" : "", sizeof_kmp_task_t, + sizeof_shareds, task_entry)); +#else KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s %s) " "sizeof_task=%ld sizeof_shared=%ld entry=%p\n", gtid, loc_ref, input_flags->tiedness ? "tied " : "untied", input_flags->proxy ? "proxy" : "", sizeof_kmp_task_t, sizeof_shareds, task_entry)); +#endif #else KA_TRACE(10, ("__kmpc_omp_task_alloc(enter): T#%d loc=%p, flags=(%s) " "sizeof_task=%ld sizeof_shared=%ld entry=%p\n", @@ -3914,6 +3962,58 @@ taskdata)); } +#if OMP_50_ENABLED +kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, int gtid, + kmp_task_t *task) { + kmp_taskdata_t *td = KMP_TASK_TO_TASKDATA(task); + if (td->td_allow_completion_event.type == KMP_EVENT_UNINITIALIZED) { + td->td_allow_completion_event.type = KMP_EVENT_ALLOW_COMPLETION; + td->td_allow_completion_event.ed.task = task; + __kmp_init_tas_lock(&td->td_allow_completion_event.lock); + } + return &td->td_allow_completion_event; +} + +void __kmp_fulfill_event(kmp_event_t *event) { + if (event->type == KMP_EVENT_ALLOW_COMPLETION) { + kmp_task_t *ptask = event->ed.task; + kmp_taskdata_t *taskdata = KMP_TASK_TO_TASKDATA(ptask); + bool detached = false; + int gtid = __kmp_get_gtid(); + + if (taskdata->td_flags.proxy == TASK_PROXY) { + // The associated task code completed before this call and detached. + detached = true; + event->type = KMP_EVENT_UNINITIALIZED; + } else { + // The associated task has not completed but could be completing at this + // point. + // We need to take the lock to avoid races + __kmp_acquire_tas_lock(&event->lock, gtid); + if (taskdata->td_flags.proxy == TASK_PROXY) + detached = true; + event->type = KMP_EVENT_UNINITIALIZED; + __kmp_release_tas_lock(&event->lock, gtid); + } + + if (detached) { + // If the task detached complete the proxy task + if (gtid >= 0) { + kmp_team_t *team = taskdata->td_team; + kmp_info_t *thread = __kmp_get_thread(); + if (thread->th.th_team == team) { + __kmpc_proxy_task_completed(gtid, ptask); + return; + } + } + + // fallback + __kmpc_proxy_task_completed_ooo(ptask); + } + } +} +#endif + // __kmp_task_dup_alloc: Allocate the taskdata and make a copy of source task // for taskloop // Index: openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t1.c =================================================================== --- openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t1.c +++ openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t1.c @@ -0,0 +1,113 @@ +// RUN: %libomp-compile && env OMP_NUM_THREADS='3' %libomp-run +// RUN: %libomp-compile && env OMP_NUM_THREADS='1' %libomp-run + +#include +#include +#include "omp_my_sleep.h" + +// detached untied +#define PTASK_FLAG_DETACHABLE 0x40 + +// OpenMP RTL interfaces +typedef unsigned long long kmp_uint64; +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 ptask __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, int gtid, ptask task); +extern omp_event_handle_t __kmpc_task_allow_completion_event( + ident_t *loc_ref, int gtid, ptask task); +#if __cplusplus +} +#endif + +int volatile checker; + +// User's code, outlined into task entry +int task_entry(int gtid, ptask task) { + checker = 1; + return 0; +} + +int main() { + int i, j, gtid = __kmpc_global_thread_num(NULL); + int nt = omp_get_max_threads(); + ptask task; + pshareds psh; + checker = 0; + omp_set_dynamic(0); + #pragma omp parallel //num_threads(N) + { + #pragma omp master + { + int gtid = __kmpc_global_thread_num(NULL); + omp_event_handle_t evt; +/* + #pragma omp task detach(evt) + {} +*/ + task = (ptask)__kmpc_omp_task_alloc(NULL,gtid,PTASK_FLAG_DETACHABLE,sizeof(struct task),sizeof(struct shar),&task_entry); + psh = task->shareds; + evt = (omp_event_handle_t)__kmpc_task_allow_completion_event(NULL,gtid,task); + task->evt = evt; + + __kmpc_omp_task(NULL, gtid, task); + my_sleep(2.0); + omp_fulfill_event(evt); + + } // end master + } // end parallel + + // check results + if (checker == 1) { + printf("passed\n"); + return 0; + } else { + printf("failed\n"); + return 1; + } +} Index: openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t2.c =================================================================== --- openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t2.c +++ openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t2.c @@ -0,0 +1,116 @@ +// RUN: %libomp-compile && env OMP_NUM_THREADS='3' %libomp-run +// RUN: %libomp-compile && env OMP_NUM_THREADS='1' %libomp-run + +#include +#include +#include "omp_my_sleep.h" + +// detached tied +#define PTASK_FLAG_DETACHABLE 0x41 + +// OpenMP RTL interfaces +typedef unsigned long long kmp_uint64; +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, int 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; + +// User's code, outlined into task entry +int task_entry(int gtid, ptask task) { + my_sleep(2.0); + checker = 1; + return 0; +} + +int main() { + int i, j, gtid = __kmpc_global_thread_num(NULL); + int nt = omp_get_max_threads(); + ptask task; + pshareds psh; + checker = 0; + omp_set_dynamic(0); + #pragma omp parallel //num_threads(N) + { + #pragma omp master + { + int gtid = __kmpc_global_thread_num(NULL); + omp_event_handle_t evt; +/* + #pragma omp task detach(evt) + {} +*/ + task = (ptask)__kmpc_omp_task_alloc(NULL,gtid,PTASK_FLAG_DETACHABLE, + sizeof(struct task),sizeof(struct shar),&task_entry); + psh = task->shareds; + evt = (omp_event_handle_t)__kmpc_task_allow_completion_event(NULL,gtid,task); + task->evt = evt; + __kmpc_omp_task(NULL, gtid, task); + omp_fulfill_event(evt); + #pragma omp taskwait + ; +// printf("after tw %d\n", omp_get_thread_num()); + } // end master + } // end parallel + + // check results + if (checker == 1) { + printf("passed\n"); + return 0; + } else { + printf("failed\n"); + return 1; + } +} Index: openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t3.c =================================================================== --- openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t3.c +++ openmp/trunk/runtime/test/tasking/kmp_detach_tasks_t3.c @@ -0,0 +1,138 @@ +// RUN: %libomp-compile && env OMP_NUM_THREADS='3' %libomp-run +// RUN: %libomp-compile && env OMP_NUM_THREADS='1' %libomp-run +// The runtime currently does not get dependency information from GCC. +// UNSUPPORTED: gcc + +#include +#include +#include "omp_my_sleep.h" + +// detached untied +#define PTASK_FLAG_DETACHABLE 0x40 + +// OpenMP RTL interfaces +typedef unsigned long long kmp_uint64; +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 struct DEP { + size_t addr; + size_t len; + int flags; +} dep; + +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_with_deps(id *loc, int gtid, ptask task, int nd, + dep *dep_lst, int nd_noalias, dep *noalias_dep_lst); +extern int __kmpc_omp_task(id *loc, int 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; + +// User's code, outlined into task entry +int task_entry(int gtid, ptask task) { + checker = 1; + return 0; +} + +int main() { + int i, j, gtid = __kmpc_global_thread_num(NULL); + int nt = omp_get_max_threads(); + ptask task; + pshareds psh; + checker = 0; + omp_set_dynamic(0); + #pragma omp parallel //num_threads(N) + { + #pragma omp master + { + #pragma omp task depend(inout:nt) + { + my_sleep(2.0); + } + int gtid = __kmpc_global_thread_num(NULL); + omp_event_handle_t evt; +/* + #pragma omp task detach(evt) + {} +*/ + task = (ptask)__kmpc_omp_task_alloc(NULL,gtid,PTASK_FLAG_DETACHABLE, + sizeof(struct task),sizeof(struct shar),&task_entry); + psh = task->shareds; + evt = (omp_event_handle_t)__kmpc_task_allow_completion_event(NULL,gtid,task); + task->evt = evt; + + dep sdep; + sdep.addr = (size_t)&nt; + sdep.len = 0L; + sdep.flags = 3; + + __kmpc_omp_task_with_deps(NULL,gtid,task,1,&sdep,0,0); + //__kmpc_omp_task(NULL, gtid, task); + + omp_fulfill_event(evt); + + #pragma omp taskwait + ; +// printf("after tw %d\n", omp_get_thread_num()); + } // end master + } // end parallel + + // check results + if (checker == 1) { + printf("passed\n"); + return 0; + } else { + printf("failed\n"); + return 1; + } +}