diff options
| -rw-r--r-- | openmp/runtime/src/dllexports | 3 | ||||
| -rw-r--r-- | openmp/runtime/src/include/50/omp.h.var | 9 | ||||
| -rw-r--r-- | openmp/runtime/src/include/50/omp_lib.f.var | 31 | ||||
| -rw-r--r-- | openmp/runtime/src/include/50/omp_lib.f90.var | 19 | ||||
| -rw-r--r-- | openmp/runtime/src/include/50/omp_lib.h.var | 22 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp.h | 31 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_csupport.cpp | 39 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_dispatch.cpp | 4 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_dispatch_hier.h | 4 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_ftn_entry.h | 38 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_ftn_os.h | 8 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_global.cpp | 6 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_gsupport.cpp | 8 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_runtime.cpp | 102 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_tasking.cpp | 2 | ||||
| -rw-r--r-- | openmp/runtime/src/kmp_wait_release.h | 33 | ||||
| -rw-r--r-- | openmp/runtime/src/z_Linux_util.cpp | 25 | ||||
| -rw-r--r-- | openmp/runtime/src/z_Windows_NT_util.cpp | 24 | ||||
| -rw-r--r-- | openmp/runtime/test/api/omp_pause_resource.c | 58 | 
19 files changed, 456 insertions, 10 deletions
diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports index 9885f87bf48..f0f2ee6f1e7 100644 --- a/openmp/runtime/src/dllexports +++ b/openmp/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/openmp/runtime/src/include/50/omp.h.var b/openmp/runtime/src/include/50/omp.h.var index 872b8f5007d..09c8cda96a1 100644 --- a/openmp/runtime/src/include/50/omp.h.var +++ b/openmp/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/openmp/runtime/src/include/50/omp_lib.f.var b/openmp/runtime/src/include/50/omp_lib.f.var index bebb6e9de94..2c534e2a8ff 100644 --- a/openmp/runtime/src/include/50/omp_lib.f.var +++ b/openmp/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/openmp/runtime/src/include/50/omp_lib.f90.var b/openmp/runtime/src/include/50/omp_lib.f90.var index e0233de81d7..a1c0128b6b1 100644 --- a/openmp/runtime/src/include/50/omp_lib.f90.var +++ b/openmp/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/openmp/runtime/src/include/50/omp_lib.h.var b/openmp/runtime/src/include/50/omp_lib.h.var index 605b410dd82..fe6716b288d 100644 --- a/openmp/runtime/src/include/50/omp_lib.h.var +++ b/openmp/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/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 599cbf23a58..8c0913ca82a 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/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/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp index 61d4a930112..b5f65fa3dbf 100644 --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/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/openmp/runtime/src/kmp_dispatch.cpp b/openmp/runtime/src/kmp_dispatch.cpp index 1090e9de1d0..b957c566ce1 100644 --- a/openmp/runtime/src/kmp_dispatch.cpp +++ b/openmp/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/openmp/runtime/src/kmp_dispatch_hier.h b/openmp/runtime/src/kmp_dispatch_hier.h index 8277eaa5a04..48b164e88b2 100644 --- a/openmp/runtime/src/kmp_dispatch_hier.h +++ b/openmp/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/openmp/runtime/src/kmp_ftn_entry.h b/openmp/runtime/src/kmp_ftn_entry.h index c08e31b034d..09be9bae56e 100644 --- a/openmp/runtime/src/kmp_ftn_entry.h +++ b/openmp/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/openmp/runtime/src/kmp_ftn_os.h b/openmp/runtime/src/kmp_ftn_os.h index 776db392a68..33f13097088 100644 --- a/openmp/runtime/src/kmp_ftn_os.h +++ b/openmp/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/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp index 5f38009af8f..37903a661b2 100644 --- a/openmp/runtime/src/kmp_global.cpp +++ b/openmp/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/openmp/runtime/src/kmp_gsupport.cpp b/openmp/runtime/src/kmp_gsupport.cpp index c1f9bdd24c5..33b0ebe06ad 100644 --- a/openmp/runtime/src/kmp_gsupport.cpp +++ b/openmp/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/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index 0db376159fc..821012bb3d4 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/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/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp index 7292ed1452d..084583e4db9 100644 --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/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/openmp/runtime/src/kmp_wait_release.h b/openmp/runtime/src/kmp_wait_release.h index dd56c88b0e4..5cd7b9af31d 100644 --- a/openmp/runtime/src/kmp_wait_release.h +++ b/openmp/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/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index aa0302c0fc3..eb6c3c0b4ce 100644 --- a/openmp/runtime/src/z_Linux_util.cpp +++ b/openmp/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/openmp/runtime/src/z_Windows_NT_util.cpp b/openmp/runtime/src/z_Windows_NT_util.cpp index f3d667f19f5..8b8891a60e5 100644 --- a/openmp/runtime/src/z_Windows_NT_util.cpp +++ b/openmp/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", diff --git a/openmp/runtime/test/api/omp_pause_resource.c b/openmp/runtime/test/api/omp_pause_resource.c new file mode 100644 index 00000000000..32c1120ab0e --- /dev/null +++ b/openmp/runtime/test/api/omp_pause_resource.c @@ -0,0 +1,58 @@ +// RUN: %libomp-compile-and-run +#include <stdio.h> +#include "omp_testsuite.h" + +int test_omp_pause_resource() { +  int fails, nthreads, my_dev; + +  fails = 0; +  nthreads = 0; +  my_dev = omp_get_initial_device(); + +#pragma omp parallel +#pragma omp single +  nthreads = omp_get_num_threads(); + +  if (omp_pause_resource(omp_pause_soft, my_dev)) +    fails++; + +#pragma omp parallel shared(nthreads) +#pragma omp single +  nthreads = omp_get_num_threads(); + +  if (nthreads == 0) +    fails++; +  if (omp_pause_resource(omp_pause_hard, my_dev)) +    fails++; +  nthreads = 0; + +#pragma omp parallel shared(nthreads) +#pragma omp single +  nthreads = omp_get_num_threads(); + +  if (nthreads == 0) +    fails++; +  if (omp_pause_resource_all(omp_pause_soft)) +    fails++; +  nthreads = 0; + +#pragma omp parallel shared(nthreads) +#pragma omp single +  nthreads = omp_get_num_threads(); + +  if (nthreads == 0) +    fails++; +  return fails == 0; +} + +int main() { +  int i; +  int num_failed = 0; + +  for (i = 0; i < REPETITIONS; i++) { +    if (!test_omp_pause_resource()) { +      num_failed++; +    } +  } +  return num_failed; +}  | 

