Skip to content

Commit

Permalink
Fix a race in shutdown when tasking is used.
Browse files Browse the repository at this point in the history
Patch by Terry Wilmarth.

Differential Revision: https://reviews.llvm.org/D28377

llvm-svn: 294214
  • Loading branch information
AndreyChurbanov committed Feb 6, 2017
1 parent 0fceb35 commit 581490e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 1 deletion.
5 changes: 5 additions & 0 deletions openmp/runtime/src/kmp.h
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down
27 changes: 26 additions & 1 deletion openmp/runtime/src/kmp_runtime.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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 );
Expand Down
1 change: 1 addition & 0 deletions openmp/runtime/src/kmp_tasking.cpp
Expand Up @@ -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 );

Expand Down
9 changes: 9 additions & 0 deletions openmp/runtime/src/kmp_wait_release.h
Expand Up @@ -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

Expand Down Expand Up @@ -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
}

Expand Down

0 comments on commit 581490e

Please sign in to comment.