New implementation of OpenMP 5.0 detached tasks.

Patch by Alex Duran

Differential Revision: https://reviews.llvm.org/D62485

llvm-svn: 363799
This commit is contained in:
Andrey Churbanov 2019-06-19 13:23:28 +00:00
parent 982a1cf028
commit 405037c4e6
12 changed files with 564 additions and 24 deletions

View File

@ -408,7 +408,7 @@ kmpc_set_disp_num_buffers 267
__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 @@ kmp_set_disp_num_buffers 890
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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 )

View File

@ -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 @@ typedef struct kmp_task_affinity_info {
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 @@ typedef struct kmp_tasking_flags { /* Total struct must be exactly 32 bits */
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 @@ struct kmp_taskdata { /* aligned during dynamic allocation */
// 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 @@ extern void __kmp_init_implicit_task(ident_t *loc_ref, kmp_info_t *this_thr,
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,

View File

@ -1387,6 +1387,12 @@ int FTN_STDCALL FTN_GET_SUPPORTED_ACTIVE_LEVELS(void) {
#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_GET_PARTITION_PLACE_NUMS, 45, "OMP_4.5");
// 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

View File

@ -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 */

View File

@ -874,28 +874,47 @@ static void __kmp_task_finish(kmp_int32 gtid, kmp_task_t *task,
}
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 @@ static void __kmp_task_finish(kmp_int32 gtid, kmp_task_t *task,
// 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 @@ void __kmp_init_implicit_task(ident_t *loc_ref, kmp_info_t *this_thr,
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_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
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 @@ kmp_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
#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 @@ kmp_task_t *__kmp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
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_t *__kmpc_omp_task_alloc(ident_t *loc_ref, kmp_int32 gtid,
// __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 @@ void __kmpc_proxy_task_completed_ooo(kmp_task_t *ptask) {
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
//

View File

@ -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 <stdio.h>
#include <omp.h>
#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;
}
}

View File

@ -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 <stdio.h>
#include <omp.h>
#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;
}
}

View File

@ -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 <stdio.h>
#include <omp.h>
#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;
}
}