aboutsummaryrefslogtreecommitdiff
path: root/runtime/src
diff options
context:
space:
mode:
authorJonathan Peyton <jonathan.l.peyton@intel.com>2019-01-16 20:07:39 +0000
committerJonathan Peyton <jonathan.l.peyton@intel.com>2019-01-16 20:07:39 +0000
commit4338c2574e44af967a3f5e6f190ff6636dbb2b16 (patch)
tree29f709f163e54433f1421fa2d7d9e220922ffd98 /runtime/src
parentda71b1ee45a72ae498af7d2668d17ec212e14618 (diff)
[OpenMP] Add omp_pause_resource* API
Add omp_pause_resource and omp_pause_resource_all API and enum, plus stub for internal implementation. Implemented callable helper function to do local pause, and added basic functionality for hard and soft pause. Patch by Terry Wilmarth Differential Revision: https://reviews.llvm.org/D55078 git-svn-id: https://llvm.org/svn/llvm-project/openmp/trunk@351372 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'runtime/src')
-rw-r--r--runtime/src/dllexports3
-rw-r--r--runtime/src/include/50/omp.h.var9
-rw-r--r--runtime/src/include/50/omp_lib.f.var31
-rw-r--r--runtime/src/include/50/omp_lib.f90.var19
-rw-r--r--runtime/src/include/50/omp_lib.h.var22
-rw-r--r--runtime/src/kmp.h31
-rw-r--r--runtime/src/kmp_csupport.cpp39
-rw-r--r--runtime/src/kmp_dispatch.cpp4
-rw-r--r--runtime/src/kmp_dispatch_hier.h4
-rw-r--r--runtime/src/kmp_ftn_entry.h38
-rw-r--r--runtime/src/kmp_ftn_os.h8
-rw-r--r--runtime/src/kmp_global.cpp6
-rw-r--r--runtime/src/kmp_gsupport.cpp8
-rw-r--r--runtime/src/kmp_runtime.cpp102
-rw-r--r--runtime/src/kmp_tasking.cpp2
-rw-r--r--runtime/src/kmp_wait_release.h33
-rw-r--r--runtime/src/z_Linux_util.cpp25
-rw-r--r--runtime/src/z_Windows_NT_util.cpp24
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",