diff options
Diffstat (limited to 'runtime/src')
-rw-r--r-- | runtime/src/dllexports | 3 | ||||
-rw-r--r-- | runtime/src/include/50/omp.h.var | 9 | ||||
-rw-r--r-- | runtime/src/include/50/omp_lib.f.var | 31 | ||||
-rw-r--r-- | runtime/src/include/50/omp_lib.f90.var | 19 | ||||
-rw-r--r-- | runtime/src/include/50/omp_lib.h.var | 22 | ||||
-rw-r--r-- | runtime/src/kmp.h | 31 | ||||
-rw-r--r-- | runtime/src/kmp_csupport.cpp | 39 | ||||
-rw-r--r-- | runtime/src/kmp_dispatch.cpp | 4 | ||||
-rw-r--r-- | runtime/src/kmp_dispatch_hier.h | 4 | ||||
-rw-r--r-- | runtime/src/kmp_ftn_entry.h | 38 | ||||
-rw-r--r-- | runtime/src/kmp_ftn_os.h | 8 | ||||
-rw-r--r-- | runtime/src/kmp_global.cpp | 6 | ||||
-rw-r--r-- | runtime/src/kmp_gsupport.cpp | 8 | ||||
-rw-r--r-- | runtime/src/kmp_runtime.cpp | 102 | ||||
-rw-r--r-- | runtime/src/kmp_tasking.cpp | 2 | ||||
-rw-r--r-- | runtime/src/kmp_wait_release.h | 33 | ||||
-rw-r--r-- | runtime/src/z_Linux_util.cpp | 25 | ||||
-rw-r--r-- | runtime/src/z_Windows_NT_util.cpp | 24 |
18 files changed, 398 insertions, 10 deletions
diff --git a/runtime/src/dllexports b/runtime/src/dllexports index 9885f87..f0f2ee6 100644 --- a/runtime/src/dllexports +++ b/runtime/src/dllexports @@ -406,6 +406,7 @@ kmpc_set_disp_num_buffers 267 # USED FOR 4.5 __kmpc_critical_with_hint 270 __kmpc_get_target_offload 271 __kmpc_omp_reg_task_with_affinity 272 + __kmpc_pause_resource 273 %endif %endif @@ -554,6 +555,8 @@ kmp_set_disp_num_buffers 890 ompc_get_affinity_format 753 ompc_display_affinity 754 ompc_capture_affinity 755 + omp_pause_resource 756 + omp_pause_resource_all 757 OMP_NULL_ALLOCATOR DATA omp_default_mem_alloc DATA diff --git a/runtime/src/include/50/omp.h.var b/runtime/src/include/50/omp.h.var index 872b8f5..09c8cda 100644 --- a/runtime/src/include/50/omp.h.var +++ b/runtime/src/include/50/omp.h.var @@ -249,6 +249,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 Pause Resources */ + typedef enum omp_pause_resource_t { + omp_pause_resume = 0, + omp_pause_soft = 1, + omp_pause_hard = 2 + } omp_pause_resource_t; + extern int __KAI_KMPC_CONVENTION omp_pause_resource(omp_pause_resource_t, int); + extern int __KAI_KMPC_CONVENTION omp_pause_resource_all(omp_pause_resource_t); + # undef __KAI_KMPC_CONVENTION # undef __KMP_IMP diff --git a/runtime/src/include/50/omp_lib.f.var b/runtime/src/include/50/omp_lib.f.var index bebb6e9..2c534e2 100644 --- a/runtime/src/include/50/omp_lib.f.var +++ b/runtime/src/include/50/omp_lib.f.var @@ -36,6 +36,8 @@ integer, parameter :: omp_control_tool_result_kind = omp_integer_kind integer, parameter :: omp_allocator_kind = int_ptr_kind() + integer, parameter :: omp_pause_resource_kind = omp_integer_kind + end module omp_lib_kinds module omp_lib @@ -83,6 +85,10 @@ integer (kind=omp_allocator_kind), parameter :: omp_pteam_mem_alloc = 7 integer (kind=omp_allocator_kind), parameter :: omp_thread_mem_alloc = 8 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_resume = 0 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_soft = 1 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_hard = 2 + interface ! *** @@ -283,6 +289,19 @@ integer (kind=omp_integer_kind) omp_get_device_num end function omp_get_device_num + function omp_pause_resource(kind, device_num) + use omp_lib_kinds + integer (kind=omp_pause_resource_kind) kind + integer (kind=omp_integer_kind) device_num + integer (kind=omp_integer_kind) omp_pause_resource + end function omp_pause_resource + + function omp_pause_resource_all(kind) + use omp_lib_kinds + integer (kind=omp_pause_resource_kind) kind + integer (kind=omp_integer_kind) omp_pause_resource_all + end function omp_pause_resource_all + subroutine omp_init_lock(svar) !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock @@ -621,6 +640,9 @@ !dec$ attributes alias:'OMP_GET_INITIAL_DEVICE' :: omp_get_initial_device !dec$ attributes alias:'OMP_GET_MAX_TASK_PRIORITY' :: omp_get_max_task_priority !dec$ attributes alias:'OMP_GET_DEVICE_NUM' :: omp_get_device_num +!dec$ attributes alias:'OMP_PAUSE_RESOURCE' :: omp_pause_resource +!dec$ attributes alias:'OMP_PAUSE_RESOURCE_ALL' :: omp_pause_resource_all + !dec$ attributes alias:'OMP_CONTROL_TOOL' :: omp_control_tool !dec$ attributes alias:'OMP_SET_AFFINITY_FORMAT' :: omp_set_affinity_format !dec$ attributes alias:'OMP_GET_AFFINITY_FORMAT' :: omp_get_affinity_format @@ -708,6 +730,9 @@ !dec$ attributes alias:'_OMP_GET_INITIAL_DEVICE' :: omp_get_initial_device !dec$ attributes alias:'_OMP_GET_MAX_TASK_PRIORTY' :: omp_get_max_task_priority !dec$ attributes alias:'_OMP_GET_DEVICE_NUM' :: omp_get_device_num +!dec$ attributes alias:'_OMP_PAUSE_RESOURCE' :: omp_pause_resource +!dec$ attributes alias:'_OMP_PAUSE_RESOURCE_ALL' :: omp_pause_resource_all + !dec$ attributes alias:'_OMP_CONTROL_TOOL' :: omp_control_tool !dec$ attributes alias:'_OMP_SET_AFFINITY_FORMAT' :: omp_set_affinity_format !dec$ attributes alias:'_OMP_GET_AFFINITY_FORMAT' :: omp_get_affinity_format @@ -798,6 +823,9 @@ !dec$ attributes alias:'omp_get_initial_device_'::omp_get_initial_device !dec$ attributes alias:'omp_get_max_task_priority_'::omp_get_max_task_priority !dec$ attributes alias:'omp_get_device_num_'::omp_get_device_num +!dec$ attributes alias:'omp_pause_resource_' :: omp_pause_resource +!dec$ attributes alias:'omp_pause_resource_all_' :: omp_pause_resource_all + !dec$ attributes alias:'omp_set_affinity_format_' :: omp_set_affinity_format !dec$ attributes alias:'omp_get_affinity_format_' :: omp_get_affinity_format !dec$ attributes alias:'omp_display_affinity_' :: omp_display_affinity @@ -887,6 +915,9 @@ !dec$ attributes alias:'_omp_get_initial_device_'::omp_get_initial_device !dec$ attributes alias:'_omp_get_max_task_priorty_'::omp_get_max_task_priority !dec$ attributes alias:'_omp_get_device_num_'::omp_get_device_num +!dec$ attributes alias:'_omp_pause_resource_' :: omp_pause_resource +!dec$ attributes alias:'_omp_pause_resource_all_' :: omp_pause_resource_all + !dec$ attributes alias:'_omp_init_lock_'::omp_init_lock !dec$ attributes alias:'_omp_init_lock_with_hint_'::omp_init_lock_with_hint !dec$ attributes alias:'_omp_destroy_lock_'::omp_destroy_lock diff --git a/runtime/src/include/50/omp_lib.f90.var b/runtime/src/include/50/omp_lib.f90.var index e0233de..a1c0128 100644 --- a/runtime/src/include/50/omp_lib.f90.var +++ b/runtime/src/include/50/omp_lib.f90.var @@ -33,6 +33,8 @@ integer, parameter :: omp_control_tool_result_kind = omp_integer_kind integer, parameter :: omp_allocator_kind = c_intptr_t + integer, parameter :: omp_pause_resource_kind = omp_integer_kind + end module omp_lib_kinds module omp_lib @@ -97,6 +99,10 @@ integer (kind=omp_allocator_kind), parameter :: omp_pteam_mem_alloc = 7 integer (kind=omp_allocator_kind), parameter :: omp_thread_mem_alloc = 8 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_resume = 0 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_soft = 1 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_hard = 2 + interface ! *** @@ -299,6 +305,19 @@ integer (kind=omp_integer_kind) omp_get_device_num end function omp_get_device_num + function omp_pause_resource(kind, device_num) bind(c) + use omp_lib_kinds + integer (kind=omp_pause_resource_kind), value :: kind + integer (kind=omp_integer_kind), value :: device_num + integer (kind=omp_integer_kind) omp_pause_resource + end function omp_pause_resource + + function omp_pause_resource_all(kind) bind(c) + use omp_lib_kinds + integer (kind=omp_pause_resource_kind), value :: kind + integer (kind=omp_integer_kind) omp_pause_resource_all + end function omp_pause_resource_all + subroutine omp_init_lock(svar) bind(c) !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock diff --git a/runtime/src/include/50/omp_lib.h.var b/runtime/src/include/50/omp_lib.h.var index 605b410..fe6716b 100644 --- a/runtime/src/include/50/omp_lib.h.var +++ b/runtime/src/include/50/omp_lib.h.var @@ -41,6 +41,7 @@ parameter(omp_control_tool_result_kind=omp_integer_kind) integer omp_allocator_kind parameter(omp_allocator_kind=int_ptr_kind()) + integer, parameter :: omp_pause_resource_kind = omp_integer_kind integer(kind=omp_integer_kind)openmp_version parameter(openmp_version=@LIBOMP_OMP_YEAR_MONTH@) @@ -137,6 +138,10 @@ integer(kind=omp_allocator_kind)omp_thread_mem_alloc parameter(omp_thread_mem_alloc=8) + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_resume = 0 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_soft = 1 + integer (kind=omp_pause_resource_kind), parameter :: omp_pause_hard = 2 + interface ! *** @@ -332,6 +337,19 @@ integer (kind=omp_integer_kind) omp_get_device_num end function omp_get_device_num + function omp_pause_resource(kind, device_num) bind(c) + import + integer (kind=omp_pause_resource_kind), value :: kind + integer (kind=omp_integer_kind), value :: device_num + integer (kind=omp_integer_kind) omp_pause_resource + end function omp_pause_resource + + function omp_pause_resource_all(kind) bind(c) + import + integer (kind=omp_pause_resource_kind), value :: kind + integer (kind=omp_integer_kind) omp_pause_resource_all + end function omp_pause_resource_all + subroutine omp_init_lock(svar) bind(c) !DIR$ IF(__INTEL_COMPILER.GE.1400) !DIR$ attributes known_intrinsic :: omp_init_lock @@ -652,6 +670,8 @@ !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_initial_device !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_devices !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_device_num +!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_pause_resource +!DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_pause_resource_all !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_num_teams !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_get_team_num !DIR$ ATTRIBUTES OFFLOAD:MIC :: omp_init_lock @@ -731,6 +751,8 @@ !$omp declare target(omp_get_initial_device ) !$omp declare target(omp_get_num_devices ) !$omp declare target(omp_get_device_num ) +!$omp declare target(omp_pause_resource ) +!$omp declare target(omp_pause_resource_all ) !$omp declare target(omp_get_num_teams ) !$omp declare target(omp_get_team_num ) !$omp declare target(omp_init_lock ) diff --git a/runtime/src/kmp.h b/runtime/src/kmp.h index 599cbf2..8c0913c 100644 --- a/runtime/src/kmp.h +++ b/runtime/src/kmp.h @@ -3467,6 +3467,10 @@ extern void __kmp_reap_monitor(kmp_info_t *th); extern void __kmp_reap_worker(kmp_info_t *th); extern void __kmp_terminate_thread(int gtid); +extern int __kmp_try_suspend_mx(kmp_info_t *th); +extern void __kmp_lock_suspend_mx(kmp_info_t *th); +extern void __kmp_unlock_suspend_mx(kmp_info_t *th); + extern void __kmp_suspend_32(int th_gtid, kmp_flag_32 *flag); extern void __kmp_suspend_64(int th_gtid, kmp_flag_64 *flag); extern void __kmp_suspend_oncore(int th_gtid, kmp_flag_oncore *flag); @@ -4007,6 +4011,33 @@ extern int __kmpc_get_target_offload(); #define KMP_DEVICE_ALL -11 // This is libomptarget's "all devices". #endif // OMP_40_ENABLED +#if OMP_50_ENABLED +// OMP Pause Resource + +// The following enum is used both to set the status in __kmp_pause_status, and +// as the internal equivalent of the externally-visible omp_pause_resource_t. +typedef enum kmp_pause_status_t { + kmp_not_paused = 0, // status is not paused, or, requesting resume + kmp_soft_paused = 1, // status is soft-paused, or, requesting soft pause + kmp_hard_paused = 2 // status is hard-paused, or, requesting hard pause +} kmp_pause_status_t; + +// This stores the pause state of the runtime +extern kmp_pause_status_t __kmp_pause_status; +extern int __kmpc_pause_resource(kmp_pause_status_t level); +extern int __kmp_pause_resource(kmp_pause_status_t level); +// Soft resume sets __kmp_pause_status, and wakes up all threads. +extern void __kmp_resume_if_soft_paused(); +// Hard resume simply resets the status to not paused. Library will appear to +// be uninitialized after hard pause. Let OMP constructs trigger required +// initializations. +static inline void __kmp_resume_if_hard_paused() { + if (__kmp_pause_status == kmp_hard_paused) { + __kmp_pause_status = kmp_not_paused; + } +} +#endif // OMP_50_ENABLED + #ifdef __cplusplus } #endif diff --git a/runtime/src/kmp_csupport.cpp b/runtime/src/kmp_csupport.cpp index 61d4a93..b5f65fa 100644 --- a/runtime/src/kmp_csupport.cpp +++ b/runtime/src/kmp_csupport.cpp @@ -485,6 +485,10 @@ void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 global_tid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + this_thr = __kmp_threads[global_tid]; serial_team = this_thr->th.th_serial_team; @@ -696,6 +700,10 @@ void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + if (__kmp_env_consistency_check) { if (loc == 0) { KMP_WARNING(ConstructIdentInvalid); // ??? What does it mean for the user? @@ -744,6 +752,10 @@ kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + if (KMP_MASTER_GTID(global_tid)) { KMP_COUNT_BLOCK(OMP_MASTER); KMP_PUSH_PARTITIONED_TIMER(OMP_master); @@ -834,6 +846,10 @@ void __kmpc_ordered(ident_t *loc, kmp_int32 gtid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + #if USE_ITT_BUILD __kmp_itt_ordered_prep(gtid); // TODO: ordered_wait_id @@ -1590,6 +1606,10 @@ kmp_int32 __kmpc_barrier_master(ident_t *loc, kmp_int32 global_tid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + if (__kmp_env_consistency_check) __kmp_check_barrier(global_tid, ct_barrier, loc); @@ -1648,6 +1668,10 @@ kmp_int32 __kmpc_barrier_master_nowait(ident_t *loc, kmp_int32 global_tid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + if (__kmp_env_consistency_check) { if (loc == 0) { KMP_WARNING(ConstructIdentInvalid); // ??? What does it mean for the user? @@ -3366,6 +3390,10 @@ __kmpc_reduce_nowait(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + // check correctness of reduce block nesting #if KMP_USE_DYNAMIC_LOCK if (__kmp_env_consistency_check) @@ -3586,6 +3614,10 @@ kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, kmp_int32 num_vars, if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + // check correctness of reduce block nesting #if KMP_USE_DYNAMIC_LOCK if (__kmp_env_consistency_check) @@ -4159,6 +4191,13 @@ int __kmpc_get_target_offload(void) { } return __kmp_target_offload; } + +int __kmpc_pause_resource(kmp_pause_status_t level) { + if (!__kmp_init_serial) { + return 1; // Can't pause if runtime is not initialized + } + return __kmp_pause_resource(level); +} #endif // OMP_50_ENABLED // end of file // diff --git a/runtime/src/kmp_dispatch.cpp b/runtime/src/kmp_dispatch.cpp index 1090e9d..b957c56 100644 --- a/runtime/src/kmp_dispatch.cpp +++ b/runtime/src/kmp_dispatch.cpp @@ -740,6 +740,10 @@ __kmp_dispatch_init(ident_t *loc, int gtid, enum sched_type schedule, T lb, if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + #if INCLUDE_SSC_MARKS SSC_MARK_DISPATCH_INIT(); #endif diff --git a/runtime/src/kmp_dispatch_hier.h b/runtime/src/kmp_dispatch_hier.h index 8277eaa..48b164e 100644 --- a/runtime/src/kmp_dispatch_hier.h +++ b/runtime/src/kmp_dispatch_hier.h @@ -924,6 +924,10 @@ void __kmp_dispatch_init_hierarchy(ident_t *loc, int n, KMP_DEBUG_ASSERT(new_chunks); if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + th = __kmp_threads[gtid]; team = th->th.th_team; active = !team->t.t_serialized; diff --git a/runtime/src/kmp_ftn_entry.h b/runtime/src/kmp_ftn_entry.h index c08e31b..09be9ba 100644 --- a/runtime/src/kmp_ftn_entry.h +++ b/runtime/src/kmp_ftn_entry.h @@ -1332,6 +1332,42 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_MAX_TASK_PRIORITY)(void) { // Compiler/libomptarget will handle this if called inside target. int FTN_STDCALL FTN_GET_DEVICE_NUM(void) KMP_WEAK_ATTRIBUTE; int FTN_STDCALL FTN_GET_DEVICE_NUM(void) { return KMP_HOST_DEVICE; } + +// Compiler will ensure that this is only called from host in sequential region +int FTN_STDCALL FTN_PAUSE_RESOURCE(kmp_pause_status_t kind, int device_num) { +#ifdef KMP_STUB + return 1; // just fail +#else + if (device_num == KMP_HOST_DEVICE) + return __kmpc_pause_resource(kind); + else { +#if !KMP_OS_WINDOWS + int (*fptr)(kmp_pause_status_t, int); + if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "tgt_pause_resource"))) + return (*fptr)(kind, device_num); + else +#endif + return 1; // just fail if there is no libomptarget + } +#endif +} + +// Compiler will ensure that this is only called from host in sequential region +int FTN_STDCALL FTN_PAUSE_RESOURCE_ALL(kmp_pause_status_t kind) { +#ifdef KMP_STUB + return 1; // just fail +#else + int fails = 0; +#if !KMP_OS_WINDOWS + int (*fptr)(kmp_pause_status_t, int); + if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "tgt_pause_resource"))) + fails = (*fptr)(kind, KMP_DEVICE_ALL); // pause devices +#endif + fails += __kmpc_pause_resource(kind); // pause host + return fails; +#endif +} + #endif // OMP_50_ENABLED // GCC compatibility (versioned symbols) @@ -1435,6 +1471,8 @@ KMP_VERSION_SYMBOL(FTN_GET_PARTITION_PLACE_NUMS, 45, "OMP_4.5"); #if OMP_50_ENABLED // OMP_5.0 versioned symbols // KMP_VERSION_SYMBOL(FTN_GET_DEVICE_NUM, 50, "OMP_5.0"); +// KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE, 50, "OMP_5.0"); +// KMP_VERSION_SYMBOL(FTN_PAUSE_RESOURCE_ALL, 50, "OMP_5.0"); #endif #endif // KMP_USE_VERSION_SYMBOLS diff --git a/runtime/src/kmp_ftn_os.h b/runtime/src/kmp_ftn_os.h index 776db39..33f1309 100644 --- a/runtime/src/kmp_ftn_os.h +++ b/runtime/src/kmp_ftn_os.h @@ -142,6 +142,8 @@ #define FTN_GET_AFFINITY_FORMAT omp_get_affinity_format #define FTN_DISPLAY_AFFINITY omp_display_affinity #define FTN_CAPTURE_AFFINITY omp_capture_affinity +#define FTN_PAUSE_RESOURCE omp_pause_resource +#define FTN_PAUSE_RESOURCE_ALL omp_pause_resource_all #endif #endif /* KMP_FTN_PLAIN */ @@ -271,6 +273,8 @@ #define FTN_GET_AFFINITY_FORMAT omp_get_affinity_format_ #define FTN_DISPLAY_AFFINITY omp_display_affinity_ #define FTN_CAPTURE_AFFINITY omp_capture_affinity_ +#define FTN_PAUSE_RESOURCE omp_pause_resource_ +#define FTN_PAUSE_RESOURCE_ALL omp_pause_resource_all_ #endif #endif /* KMP_FTN_APPEND */ @@ -400,6 +404,8 @@ #define FTN_GET_AFFINITY_FORMAT OMP_GET_AFFINITY_FORMAT #define FTN_DISPLAY_AFFINITY OMP_DISPLAY_AFFINITY #define FTN_CAPTURE_AFFINITY OMP_CAPTURE_AFFINITY +#define FTN_PAUSE_RESOURCE OMP_PAUSE_RESOURCE +#define FTN_PAUSE_RESOURCE_ALL OMP_PAUSE_RESOURCE_ALL #endif #endif /* KMP_FTN_UPPER */ @@ -529,6 +535,8 @@ #define FTN_GET_AFFINITY_FORMAT OMP_GET_AFFINITY_FORMAT_ #define FTN_DISPLAY_AFFINITY OMP_DISPLAY_AFFINITY_ #define FTN_CAPTURE_AFFINITY OMP_CAPTURE_AFFINITY_ +#define FTN_PAUSE_RESOURCE OMP_PAUSE_RESOURCE_ +#define FTN_PAUSE_RESOURCE_ALL OMP_PAUSE_RESOURCE_ALL_ #endif #endif /* KMP_FTN_UAPPEND */ diff --git a/runtime/src/kmp_global.cpp b/runtime/src/kmp_global.cpp index 5f38009..37903a6 100644 --- a/runtime/src/kmp_global.cpp +++ b/runtime/src/kmp_global.cpp @@ -533,5 +533,9 @@ int _You_must_link_with_Microsoft_OpenMP_library = 1; #if OMP_50_ENABLED kmp_target_offload_kind_t __kmp_target_offload = tgt_default; -#endif + +// OMP Pause Resources +kmp_pause_status_t __kmp_pause_status = kmp_not_paused; +#endif // OMP_50_ENABLED + // end of file // diff --git a/runtime/src/kmp_gsupport.cpp b/runtime/src/kmp_gsupport.cpp index c1f9bdd..33b0ebe 100644 --- a/runtime/src/kmp_gsupport.cpp +++ b/runtime/src/kmp_gsupport.cpp @@ -120,6 +120,10 @@ int KMP_EXPAND_NAME(KMP_API_NAME_GOMP_SINGLE_START)(void) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + // 3rd parameter == FALSE prevents kmp_enter_single from pushing a // workshare when USE_CHECKS is defined. We need to avoid the push, // as there is no corresponding GOMP_single_end() call. @@ -168,6 +172,10 @@ void *KMP_EXPAND_NAME(KMP_API_NAME_GOMP_SINGLE_COPY_START)(void) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + // If this is the first thread to enter, return NULL. The generated code will // then call GOMP_single_copy_end() for this thread only, with the // copyprivate data pointer as an argument. diff --git a/runtime/src/kmp_runtime.cpp b/runtime/src/kmp_runtime.cpp index 0db3761..821012b 100644 --- a/runtime/src/kmp_runtime.cpp +++ b/runtime/src/kmp_runtime.cpp @@ -752,6 +752,10 @@ int __kmp_enter_single(int gtid, ident_t *id_ref, int push_ws) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + th = __kmp_threads[gtid]; team = th->th.th_team; status = 0; @@ -1189,6 +1193,10 @@ void __kmp_serialized_parallel(ident_t *loc, kmp_int32 global_tid) { if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + this_thr = __kmp_threads[global_tid]; serial_team = this_thr->th.th_serial_team; @@ -1492,6 +1500,10 @@ int __kmp_fork_call(ident_t *loc, int gtid, if (!TCR_4(__kmp_init_parallel)) __kmp_parallel_initialize(); +#if OMP_50_ENABLED + __kmp_resume_if_soft_paused(); +#endif + /* setup current data */ master_th = __kmp_threads[gtid]; // AC: potentially unsafe, not in sync with // shutdown @@ -5851,7 +5863,6 @@ static void __kmp_reap_thread(kmp_info_t *thread, int is_root) { gtid = thread->th.th_info.ds.ds_gtid; if (!is_root) { - if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { /* Assume the threads are at the fork barrier here */ KA_TRACE( @@ -6272,8 +6283,10 @@ void __kmp_internal_end_thread(int gtid_req) { // OM: Removed Linux* OS restriction to fix the crash on OS X* (DPD200239966) // and Windows(DPD200287443) that occurs when using critical sections from // foreign threads. - KA_TRACE(10, ("__kmp_internal_end_thread: exiting T#%d\n", gtid_req)); - return; + if (__kmp_pause_status != kmp_hard_paused) { + KA_TRACE(10, ("__kmp_internal_end_thread: exiting T#%d\n", gtid_req)); + return; + } #endif /* synchronize the termination process */ __kmp_acquire_bootstrap_lock(&__kmp_initz_lock); @@ -6920,6 +6933,10 @@ void __kmp_parallel_initialize(void) { __kmp_do_middle_initialize(); } +#if OMP_50_ENABLED + __kmp_resume_if_hard_paused(); +#endif + /* begin initialization */ KA_TRACE(10, ("__kmp_parallel_initialize: enter\n")); KMP_ASSERT(KMP_UBER_GTID(gtid)); @@ -8190,3 +8207,82 @@ __kmp_determine_reduction_method( kmp_int32 __kmp_get_reduce_method(void) { return ((__kmp_entry_thread()->th.th_local.packed_reduction_method) >> 8); } + +#if OMP_50_ENABLED + +// Soft pause sets up threads to ignore blocktime and just go to sleep. +// Spin-wait code checks __kmp_pause_status and reacts accordingly. +void __kmp_soft_pause() { __kmp_pause_status = kmp_soft_paused; } + +// Hard pause shuts down the runtime completely. Resume happens naturally when +// OpenMP is used subsequently. +void __kmp_hard_pause() { + __kmp_pause_status = kmp_hard_paused; + __kmp_internal_end_thread(-1); +} + +// Soft resume sets __kmp_pause_status, and wakes up all threads. +void __kmp_resume_if_soft_paused() { + if (__kmp_pause_status == kmp_soft_paused) { + __kmp_pause_status = kmp_not_paused; + + for (int gtid = 1; gtid < __kmp_threads_capacity; ++gtid) { + kmp_info_t *thread = __kmp_threads[gtid]; + if (thread) { // Wake it if sleeping + kmp_flag_64 fl(&thread->th.th_bar[bs_forkjoin_barrier].bb.b_go, thread); + if (fl.is_sleeping()) + fl.resume(gtid); + else if (__kmp_try_suspend_mx(thread)) { // got suspend lock + __kmp_unlock_suspend_mx(thread); // unlock it; it won't sleep + } else { // thread holds the lock and may sleep soon + do { // until either the thread sleeps, or we can get the lock + if (fl.is_sleeping()) { + fl.resume(gtid); + break; + } else if (__kmp_try_suspend_mx(thread)) { + __kmp_unlock_suspend_mx(thread); + break; + } + } while (1); + } + } + } + } +} + +// This function is called via __kmpc_pause_resource. Returns 0 if successful. +// TODO: add warning messages +int __kmp_pause_resource(kmp_pause_status_t level) { + if (level == kmp_not_paused) { // requesting resume + if (__kmp_pause_status == kmp_not_paused) { + // error message about runtime not being paused, so can't resume + return 1; + } else { + KMP_DEBUG_ASSERT(__kmp_pause_status == kmp_soft_paused || + __kmp_pause_status == kmp_hard_paused); + __kmp_pause_status = kmp_not_paused; + return 0; + } + } else if (level == kmp_soft_paused) { // requesting soft pause + if (__kmp_pause_status != kmp_not_paused) { + // error message about already being paused + return 1; + } else { + __kmp_soft_pause(); + return 0; + } + } else if (level == kmp_hard_paused) { // requesting hard pause + if (__kmp_pause_status != kmp_not_paused) { + // error message about already being paused + return 1; + } else { + __kmp_hard_pause(); + return 0; + } + } else { + // error message about invalid level + return 1; + } +} + +#endif // OMP_50_ENABLED diff --git a/runtime/src/kmp_tasking.cpp b/runtime/src/kmp_tasking.cpp index 7292ed1..084583e 100644 --- a/runtime/src/kmp_tasking.cpp +++ b/runtime/src/kmp_tasking.cpp @@ -2839,7 +2839,7 @@ static void __kmp_enable_tasking(kmp_task_team_t *task_team, threads_data = (kmp_thread_data_t *)TCR_PTR(task_team->tt.tt_threads_data); KMP_DEBUG_ASSERT(threads_data != NULL); - if ((__kmp_tasking_mode == tskm_task_teams) && + if (__kmp_tasking_mode == tskm_task_teams && (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME)) { // Release any threads sleeping at the barrier, so that they can steal // tasks and execute them. In extra barrier mode, tasks do not sleep diff --git a/runtime/src/kmp_wait_release.h b/runtime/src/kmp_wait_release.h index dd56c88..5cd7b9a 100644 --- a/runtime/src/kmp_wait_release.h +++ b/runtime/src/kmp_wait_release.h @@ -268,12 +268,20 @@ final_spin=FALSE) // Setup for waiting KMP_INIT_YIELD(spins); - if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME) { + if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME +#if OMP_50_ENABLED + || __kmp_pause_status == kmp_soft_paused +#endif + ) { #if KMP_USE_MONITOR // The worker threads cannot rely on the team struct existing at this point. // Use the bt values cached in the thread struct instead. #ifdef KMP_ADJUST_BLOCKTIME - if (__kmp_zero_bt && !this_thr->th.th_team_bt_set) + if ( +#if OMP_50_ENABLED + __kmp_pause_status == kmp_soft_paused || +#endif + (__kmp_zero_bt && !this_thr->th.th_team_bt_set)) // Force immediate suspend if not set by user and more threads than // available procs hibernate = 0; @@ -296,7 +304,13 @@ final_spin=FALSE) th_gtid, __kmp_global.g.g_time.dt.t_value, hibernate, hibernate - __kmp_global.g.g_time.dt.t_value)); #else - hibernate_goal = KMP_NOW() + this_thr->th.th_team_bt_intervals; +#if OMP_50_ENABLED + if (__kmp_pause_status == kmp_soft_paused) { + // Force immediate suspend + hibernate_goal = KMP_NOW(); + } else +#endif + hibernate_goal = KMP_NOW() + this_thr->th.th_team_bt_intervals; poll_count = 0; #endif // KMP_USE_MONITOR } @@ -389,7 +403,11 @@ final_spin=FALSE) #endif // Don't suspend if KMP_BLOCKTIME is set to "infinite" - if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME) + if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME +#if OMP_50_ENABLED + && __kmp_pause_status != kmp_soft_paused +#endif + ) continue; // Don't suspend if there is a likelihood of new tasks being spawned. @@ -405,7 +423,14 @@ final_spin=FALSE) continue; #endif +#if OMP_50_ENABLED + if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && + __kmp_pause_status != kmp_soft_paused) + continue; +#endif + KF_TRACE(50, ("__kmp_wait_sleep: T#%d suspend time reached\n", th_gtid)); + #if KMP_OS_UNIX if (final_spin) KMP_ATOMIC_ST_REL(&this_thr->th.th_blocking, false); diff --git a/runtime/src/z_Linux_util.cpp b/runtime/src/z_Linux_util.cpp index aa0302c..eb6c3c0 100644 --- a/runtime/src/z_Linux_util.cpp +++ b/runtime/src/z_Linux_util.cpp @@ -1414,6 +1414,21 @@ void __kmp_suspend_uninitialize_thread(kmp_info_t *th) { } } +// return true if lock obtained, false otherwise +int __kmp_try_suspend_mx(kmp_info_t *th) { + return (pthread_mutex_trylock(&th->th.th_suspend_mx.m_mutex) == 0); +} + +void __kmp_lock_suspend_mx(kmp_info_t *th) { + int status = pthread_mutex_lock(&th->th.th_suspend_mx.m_mutex); + KMP_CHECK_SYSFAIL("pthread_mutex_lock", status); +} + +void __kmp_unlock_suspend_mx(kmp_info_t *th) { + int status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex); + KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); +} + /* This routine puts the calling thread to sleep after setting the sleep bit for the indicated flag variable to true. */ template <class C> @@ -1437,7 +1452,15 @@ static inline void __kmp_suspend_template(int th_gtid, C *flag) { /* TODO: shouldn't this use release semantics to ensure that __kmp_suspend_initialize_thread gets called first? */ old_spin = flag->set_sleeping(); - +#if OMP_50_ENABLED + if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && + __kmp_pause_status != kmp_soft_paused) { + flag->unset_sleeping(); + status = pthread_mutex_unlock(&th->th.th_suspend_mx.m_mutex); + KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status); + return; + } +#endif KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for spin(%p)==%x," " was %x\n", th_gtid, flag->get(), flag->load(), old_spin)); diff --git a/runtime/src/z_Windows_NT_util.cpp b/runtime/src/z_Windows_NT_util.cpp index f3d667f..8b8891a 100644 --- a/runtime/src/z_Windows_NT_util.cpp +++ b/runtime/src/z_Windows_NT_util.cpp @@ -159,6 +159,10 @@ void __kmp_win32_mutex_lock(kmp_win32_mutex_t *mx) { EnterCriticalSection(&mx->cs); } +int __kmp_win32_mutex_trylock(kmp_win32_mutex_t *mx) { + return TryEnterCriticalSection(&mx->cs); +} + void __kmp_win32_mutex_unlock(kmp_win32_mutex_t *mx) { LeaveCriticalSection(&mx->cs); } @@ -300,6 +304,18 @@ void __kmp_suspend_uninitialize_thread(kmp_info_t *th) { } } +int __kmp_try_suspend_mx(kmp_info_t *th) { + return __kmp_win32_mutex_trylock(&th->th.th_suspend_mx); +} + +void __kmp_lock_suspend_mx(kmp_info_t *th) { + __kmp_win32_mutex_lock(&th->th.th_suspend_mx); +} + +void __kmp_unlock_suspend_mx(kmp_info_t *th) { + __kmp_win32_mutex_unlock(&th->th.th_suspend_mx); +} + /* This routine puts the calling thread to sleep after setting the sleep bit for the indicated flag variable to true. */ template <class C> @@ -321,6 +337,14 @@ static inline void __kmp_suspend_template(int th_gtid, C *flag) { /* TODO: shouldn't this use release semantics to ensure that __kmp_suspend_initialize_thread gets called first? */ old_spin = flag->set_sleeping(); +#if OMP_50_ENABLED + if (__kmp_dflt_blocktime == KMP_MAX_BLOCKTIME && + __kmp_pause_status != kmp_soft_paused) { + flag->unset_sleeping(); + __kmp_win32_mutex_unlock(&th->th.th_suspend_mx); + return; + } +#endif KF_TRACE(5, ("__kmp_suspend_template: T#%d set sleep bit for flag's" " loc(%p)==%d\n", |