[OpenMP] Fix a few issues with hidden helper task

This patch includes the following changes to address a few issues when
using hidden helper task.

- Assertion is triggered when there are inadvertent calls to hidden
  helper functions on non-Linux OS
- Added deinit code in __kmp_internal_end_library function to fix random
  shutdown crashes
- Moved task data access into the lock-guarded region in __kmp_push_task

Differential Revision: https://reviews.llvm.org/D105308
This commit is contained in:
Hansang Bae 2021-06-30 14:01:04 -05:00
parent edc1f0c12c
commit f1b9ce2736
3 changed files with 57 additions and 3 deletions

View File

@ -6204,6 +6204,16 @@ void __kmp_internal_end_library(int gtid_req) {
return;
}
// If hidden helper team has been initialized, we need to deinit it
if (TCR_4(__kmp_init_hidden_helper) &&
!TCR_4(__kmp_hidden_helper_team_done)) {
TCW_SYNC_4(__kmp_hidden_helper_team_done, TRUE);
// First release the main thread to let it continue its work
__kmp_hidden_helper_main_thread_release();
// Wait until the hidden helper team has been destroyed
__kmp_hidden_helper_threads_deinitz_wait();
}
KMP_MB(); /* Flush all pending memory write invalidates. */
/* find out who we are and what we should do */
{
@ -6317,7 +6327,8 @@ void __kmp_internal_end_thread(int gtid_req) {
}
// If hidden helper team has been initialized, we need to deinit it
if (TCR_4(__kmp_init_hidden_helper)) {
if (TCR_4(__kmp_init_hidden_helper) &&
!TCR_4(__kmp_hidden_helper_team_done)) {
TCW_SYNC_4(__kmp_hidden_helper_team_done, TRUE);
// First release the main thread to let it continue its work
__kmp_hidden_helper_main_thread_release();
@ -8697,11 +8708,12 @@ void __kmp_omp_display_env(int verbose) {
// Globals and functions for hidden helper task
kmp_info_t **__kmp_hidden_helper_threads;
kmp_info_t *__kmp_hidden_helper_main_thread;
kmp_int32 __kmp_hidden_helper_threads_num = 8;
std::atomic<kmp_int32> __kmp_unexecuted_hidden_helper_tasks;
#if KMP_OS_LINUX
kmp_int32 __kmp_hidden_helper_threads_num = 8;
kmp_int32 __kmp_enable_hidden_helper = TRUE;
#else
kmp_int32 __kmp_hidden_helper_threads_num = 0;
kmp_int32 __kmp_enable_hidden_helper = FALSE;
#endif

View File

@ -436,10 +436,12 @@ static kmp_int32 __kmp_push_task(kmp_int32 gtid, kmp_task_t *task) {
gtid, taskdata, thread_data->td.td_deque_ntasks,
thread_data->td.td_deque_head, thread_data->td.td_deque_tail));
auto hidden_helper = taskdata->td_flags.hidden_helper;
__kmp_release_bootstrap_lock(&thread_data->td.td_deque_lock);
// Signal one worker thread to execute the task
if (taskdata->td_flags.hidden_helper) {
if (UNLIKELY(hidden_helper)) {
// Wake hidden helper threads up if they're sleeping
__kmp_hidden_helper_worker_thread_signal();
}

View File

@ -25,7 +25,9 @@
#include <alloca.h>
#endif
#include <math.h> // HUGE_VAL.
#if KMP_OS_LINUX
#include <semaphore.h>
#endif // KMP_OS_LINUX
#include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/time.h>
@ -2468,6 +2470,7 @@ int __kmp_invoke_microtask(microtask_t pkfn, int gtid, int tid, int argc,
#endif
#if KMP_OS_LINUX
// Functions for hidden helper task
namespace {
// Condition variable for initializing hidden helper team
@ -2628,5 +2631,42 @@ void __kmp_hidden_helper_threads_deinitz_release() {
status = pthread_mutex_unlock(&hidden_helper_threads_deinitz_lock);
KMP_CHECK_SYSFAIL("pthread_mutex_unlock", status);
}
#else // KMP_OS_LINUX
void __kmp_hidden_helper_worker_thread_wait() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_do_initialize_hidden_helper_threads() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_threads_initz_wait() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_initz_release() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_main_thread_wait() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_main_thread_release() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_worker_thread_signal() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_threads_deinitz_wait() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
void __kmp_hidden_helper_threads_deinitz_release() {
KMP_ASSERT(0 && "Hidden helper task is not supported on this OS");
}
#endif // KMP_OS_LINUX
// end of file //