diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -3160,6 +3160,7 @@ (__kmpc_threadprivate_cached()) */ extern int __kmp_dflt_blocktime; /* number of milliseconds to wait before blocking (env setting) */ +extern bool __kmp_wpolicy_passive; /* explicitly set passive wait policy */ #if KMP_USE_MONITOR extern int __kmp_monitor_wakeups; /* number of times monitor wakes up per second */ diff --git a/openmp/runtime/src/kmp_global.cpp b/openmp/runtime/src/kmp_global.cpp --- a/openmp/runtime/src/kmp_global.cpp +++ b/openmp/runtime/src/kmp_global.cpp @@ -154,6 +154,7 @@ kmp_hier_sched_env_t __kmp_hier_scheds = {0, 0, NULL, NULL, NULL}; #endif int __kmp_dflt_blocktime = KMP_DEFAULT_BLOCKTIME; +bool __kmp_wpolicy_passive = false; #if KMP_USE_MONITOR int __kmp_monitor_wakeups = KMP_MIN_MONITOR_WAKEUPS; int __kmp_bt_intervals = KMP_INTERVALS_FROM_BLOCKTIME(KMP_DEFAULT_BLOCKTIME, diff --git a/openmp/runtime/src/kmp_settings.cpp b/openmp/runtime/src/kmp_settings.cpp --- a/openmp/runtime/src/kmp_settings.cpp +++ b/openmp/runtime/src/kmp_settings.cpp @@ -812,6 +812,7 @@ } } else if (__kmp_str_match("PASSIVE", 1, value)) { __kmp_library = library_throughput; + __kmp_wpolicy_passive = true; /* allow sleep while active tasking */ if (blocktime_str == NULL) { // KMP_BLOCKTIME not specified, so set default to 0. __kmp_dflt_blocktime = 0; diff --git a/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/runtime/src/kmp_tasking.cpp @@ -1909,8 +1909,21 @@ if (serialize_immediate) new_taskdata->td_flags.task_serial = 1; __kmp_invoke_task(gtid, new_task, current_task); + } else if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME && + __kmp_wpolicy_passive) { + kmp_info_t *this_thr = __kmp_threads[gtid]; + kmp_team_t *team = this_thr->th.th_team; + kmp_int32 nthreads = this_thr->th.th_team_nproc; + for (int i = 0; i < nthreads; ++i) { + kmp_info_t *thread = team->t.t_threads[i]; + if (thread == this_thr) + continue; + if (thread->th.th_sleep_loc != NULL) { + __kmp_null_resume_wrapper(thread); + break; // awake one thread at a time + } + } } - return TASK_CURRENT_NOT_QUEUED; } @@ -4282,6 +4295,17 @@ pass = pass << 1; } while (!__kmp_give_task(thread, k, ptask, pass)); + + if (__kmp_dflt_blocktime != KMP_MAX_BLOCKTIME && __kmp_wpolicy_passive) { + // awake at least one thread to execute given task + for (int i = 0; i < nthreads; ++i) { + thread = team->t.t_threads[i]; + if (thread->th.th_sleep_loc != NULL) { + __kmp_null_resume_wrapper(thread); + break; + } + } + } } /*! diff --git a/openmp/runtime/src/kmp_wait_release.h b/openmp/runtime/src/kmp_wait_release.h --- a/openmp/runtime/src/kmp_wait_release.h +++ b/openmp/runtime/src/kmp_wait_release.h @@ -609,7 +609,8 @@ continue; // Don't suspend if there is a likelihood of new tasks being spawned. - if ((task_team != NULL) && TCR_4(task_team->tt.tt_found_tasks)) + if (task_team != NULL && TCR_4(task_team->tt.tt_found_tasks) && + !__kmp_wpolicy_passive) continue; #if KMP_USE_MONITOR