[Openmp-commits] [openmp] r294214 - Fix a race in shutdown when tasking is used.

Andrey Churbanov via Openmp-commits openmp-commits at lists.llvm.org
Mon Feb 6 10:53:32 PST 2017


Author: achurbanov
Date: Mon Feb  6 12:53:32 2017
New Revision: 294214

URL: http://llvm.org/viewvc/llvm-project?rev=294214&view=rev
Log:
Fix a race in shutdown when tasking is used.

Patch by Terry Wilmarth.

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

Modified:
    openmp/trunk/runtime/src/kmp.h
    openmp/trunk/runtime/src/kmp_runtime.cpp
    openmp/trunk/runtime/src/kmp_tasking.cpp
    openmp/trunk/runtime/src/kmp_wait_release.h

Modified: openmp/trunk/runtime/src/kmp.h
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp.h?rev=294214&r1=294213&r2=294214&view=diff
==============================================================================
--- openmp/trunk/runtime/src/kmp.h (original)
+++ openmp/trunk/runtime/src/kmp.h Mon Feb  6 12:53:32 2017
@@ -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_
     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

Modified: openmp/trunk/runtime/src/kmp_runtime.cpp
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_runtime.cpp?rev=294214&r1=294213&r2=294214&view=diff
==============================================================================
--- openmp/trunk/runtime/src/kmp_runtime.cpp (original)
+++ openmp/trunk/runtime/src/kmp_runtime.cpp Mon Feb  6 12:53:32 2017
@@ -4004,6 +4004,12 @@ __kmp_initialize_info( kmp_info_t *this_
 
     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_t
 
     /* 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 );

Modified: openmp/trunk/runtime/src/kmp_tasking.cpp
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_tasking.cpp?rev=294214&r1=294213&r2=294214&view=diff
==============================================================================
--- openmp/trunk/runtime/src/kmp_tasking.cpp (original)
+++ openmp/trunk/runtime/src/kmp_tasking.cpp Mon Feb  6 12:53:32 2017
@@ -1884,6 +1884,7 @@ static inline int __kmp_execute_tasks_te
     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 );
 

Modified: openmp/trunk/runtime/src/kmp_wait_release.h
URL: http://llvm.org/viewvc/llvm-project/openmp/trunk/runtime/src/kmp_wait_release.h?rev=294214&r1=294213&r2=294214&view=diff
==============================================================================
--- openmp/trunk/runtime/src/kmp_wait_release.h (original)
+++ openmp/trunk/runtime/src/kmp_wait_release.h Mon Feb  6 12:53:32 2017
@@ -196,11 +196,16 @@ __kmp_wait_template(kmp_info_t *this_thr
                     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
                 __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
     }
 




More information about the Openmp-commits mailing list