Index: runtime/src/kmp.h =================================================================== --- runtime/src/kmp.h +++ runtime/src/kmp.h @@ -1611,6 +1611,9 @@ #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 */ @@ -2285,6 +2288,8 @@ 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 Index: runtime/src/kmp_runtime.cpp =================================================================== --- runtime/src/kmp_runtime.cpp +++ runtime/src/kmp_runtime.cpp @@ -4004,6 +4004,12 @@ 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 @@ -5282,6 +5288,11 @@ for ( f = 1; f < team->t.t_nproc; ++ f ) { KMP_DEBUG_ASSERT( team->t.t_threads[ f ] ); __kmp_free_thread( team->t.t_threads[ f ] ); + if (__kmp_tasking_mode != tskm_immediate_exec) { + while ((volatile kmp_uint32)team->t.t_threads[f]->th.th_reap_state + != KMP_SAFE_TO_REAP) + KMP_CPU_PAUSE(); + } team->t.t_threads[ f ] = NULL; } @@ -5841,6 +5852,7 @@ 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 ); Index: runtime/src/kmp_tasking.cpp =================================================================== --- runtime/src/kmp_tasking.cpp +++ runtime/src/kmp_tasking.cpp @@ -1884,6 +1884,7 @@ 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 ); Index: runtime/src/kmp_wait_release.h =================================================================== --- runtime/src/kmp_wait_release.h +++ runtime/src/kmp_wait_release.h @@ -212,11 +212,16 @@ 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 @@ -289,6 +294,10 @@ __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 }