diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 5859c51f365e1..4eb586c2f4f7e 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -1625,6 +1625,9 @@ typedef struct kmp_disp { #define KMP_BARRIER_SWITCH_TO_OWN_FLAG 3 // Special state; tells worker to shift from parent to own b_go #define KMP_BARRIER_SWITCHING 4 // Special state; worker resets appropriate flag on wake-up +#define KMP_NOT_SAFE_TO_REAP 0 // Thread th_reap_state: not safe to reap (tasking) +#define KMP_SAFE_TO_REAP 1 // Thread th_reap_state: safe to reap (not tasking) + enum barrier_type { bs_plain_barrier = 0, /* 0, All non-fork/join barriers (except reduction barriers if enabled) */ bs_forkjoin_barrier, /* 1, All fork/join (parallel region) barriers */ @@ -2301,6 +2304,8 @@ typedef struct KMP_ALIGN_CACHE kmp_base_info { kmp_uint8 * th_task_state_memo_stack; // Stack holding memos of th_task_state at nested levels kmp_uint32 th_task_state_top; // Top element of th_task_state_memo_stack kmp_uint32 th_task_state_stack_sz; // Size of th_task_state_memo_stack + kmp_uint32 th_reap_state; // Non-zero indicates thread is not + // tasking, thus safe to reap /* * More stuff for keeping track of active/sleeping threads diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index 567888156fbd9..454e29a2d9f71 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -4004,6 +4004,12 @@ __kmp_initialize_info( kmp_info_t *this_thr, kmp_team_t *team, int tid, int gtid this_thr->th.th_info.ds.ds_tid = tid; this_thr->th.th_set_nproc = 0; + if (__kmp_tasking_mode != tskm_immediate_exec) + // When tasking is possible, threads are not safe to reap until they are + // done tasking; this will be set when tasking code is exited in wait + this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP; + else // no tasking --> always safe to reap + this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; #if OMP_40_ENABLED this_thr->th.th_set_proc_bind = proc_bind_default; # if KMP_AFFINITY_SUPPORTED @@ -5255,7 +5261,25 @@ __kmp_free_team( kmp_root_t *root, kmp_team_t *team USE_NESTED_HOT_ARG(kmp_info /* if we are non-hot team, release our threads */ if( ! use_hot_team ) { - if ( __kmp_tasking_mode != tskm_immediate_exec ) { + if (__kmp_tasking_mode != tskm_immediate_exec) { + // Wait for threads to reach reapable state + for (f = 1; f < team->t.t_nproc; ++f) { + KMP_DEBUG_ASSERT(team->t.t_threads[f]); + volatile kmp_uint32 *state = &team->t.t_threads[f]->th.th_reap_state; + while (*state != KMP_SAFE_TO_REAP) { +#if KMP_OS_WINDOWS + // On Windows a thread can be killed at any time, check this + DWORD ecode; + if (__kmp_is_thread_alive(team->t.t_threads[f], &ecode)) + KMP_CPU_PAUSE(); + else + *state = KMP_SAFE_TO_REAP; // reset the flag for dead thread +#else + KMP_CPU_PAUSE(); +#endif + } + } + // Delete task teams int tt_idx; for (tt_idx=0; tt_idx<2; ++tt_idx) { @@ -5841,6 +5865,7 @@ __kmp_internal_end(void) kmp_info_t * thread = (kmp_info_t *) __kmp_thread_pool; __kmp_thread_pool = thread->th.th_next_pool; // Reap it. + KMP_DEBUG_ASSERT(thread->th.th_reap_state == KMP_SAFE_TO_REAP); thread->th.th_next_pool = NULL; thread->th.th_in_pool = FALSE; __kmp_reap_thread( thread, 0 ); diff --git a/openmp/runtime/src/kmp_tasking.cpp b/openmp/runtime/src/kmp_tasking.cpp index 4018b2d8f9ea3..5965822b71f02 100644 --- a/openmp/runtime/src/kmp_tasking.cpp +++ b/openmp/runtime/src/kmp_tasking.cpp @@ -1884,6 +1884,7 @@ static inline int __kmp_execute_tasks_template(kmp_info_t *thread, kmp_int32 gti KA_TRACE(15, ("__kmp_execute_tasks_template(enter): T#%d final_spin=%d *thread_finished=%d\n", gtid, final_spin, *thread_finished) ); + thread->th.th_reap_state = KMP_NOT_SAFE_TO_REAP; threads_data = (kmp_thread_data_t *)TCR_PTR(task_team -> tt.tt_threads_data); KMP_DEBUG_ASSERT( threads_data != NULL ); diff --git a/openmp/runtime/src/kmp_wait_release.h b/openmp/runtime/src/kmp_wait_release.h index 4d177897d6e9b..a3d2ba1616140 100644 --- a/openmp/runtime/src/kmp_wait_release.h +++ b/openmp/runtime/src/kmp_wait_release.h @@ -196,11 +196,16 @@ __kmp_wait_template(kmp_info_t *this_thr, C *flag, int final_spin if (KMP_TASKING_ENABLED(task_team)) flag->execute_tasks(this_thr, th_gtid, final_spin, &tasks_completed USE_ITT_BUILD_ARG(itt_sync_obj), 0); + else + this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; } else { KMP_DEBUG_ASSERT(!KMP_MASTER_TID(this_thr->th.th_info.ds.ds_tid)); this_thr->th.th_task_team = NULL; + this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; } + } else { + this_thr->th.th_reap_state = KMP_SAFE_TO_REAP; } // if } // if @@ -273,6 +278,10 @@ __kmp_wait_template(kmp_info_t *this_thr, C *flag, int final_spin __kmp_abort_thread(); break; } + else if (__kmp_tasking_mode != tskm_immediate_exec + && this_thr->th.th_reap_state == KMP_SAFE_TO_REAP) { + this_thr->th.th_reap_state = KMP_NOT_SAFE_TO_REAP; + } // TODO: If thread is done with work and times out, disband/free }