From f252010f691d7ebf896ee6465c91f454fc46e621 Mon Sep 17 00:00:00 2001 From: Jonathan Peyton Date: Mon, 18 Apr 2016 21:33:01 +0000 Subject: [PATCH] Fix for pthread_setspecific (TLS and shutdown) problem Some codes that use TLS fail intermittently because one thread tries to write TLS values after the TLS key has been destroyed by another thread. This happens when one thread executes library shutdown (and destroys TLS keys), while another thread starts to execute the TLS key destructor routine. Before this change, the kmp_init_runtime flag was checked before calling pthread_* TLS functions, but this flag is set to FALSE later than the destruction of the TLS keys, which leads to failure. The fix is to check kmp_init_gtid instead, as this flag is unset *before* the destruction of TLS keys. Differential Revision: http://reviews.llvm.org/D19022 llvm-svn: 266674 --- openmp/runtime/src/kmp_runtime.c | 2 +- openmp/runtime/src/z_Linux_util.c | 15 +++++++++------ openmp/runtime/src/z_Windows_NT_util.c | 17 ++++++++++------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/openmp/runtime/src/kmp_runtime.c b/openmp/runtime/src/kmp_runtime.c index 5952f93bb701..c2a6f9b254f2 100644 --- a/openmp/runtime/src/kmp_runtime.c +++ b/openmp/runtime/src/kmp_runtime.c @@ -3737,6 +3737,7 @@ __kmp_register_root( int initial_thread ) /* initialize the thread, get it ready to go */ __kmp_initialize_info( root_thread, root->r.r_root_team, 0, gtid ); + TCW_4(__kmp_init_gtid, TRUE); /* prepare the master thread for get_gtid() */ __kmp_gtid_set_specific( gtid ); @@ -3748,7 +3749,6 @@ __kmp_register_root( int initial_thread ) #endif __kmp_create_worker( gtid, root_thread, __kmp_stksize ); KMP_DEBUG_ASSERT( __kmp_gtid_get_specific() == gtid ); - TCW_4(__kmp_init_gtid, TRUE); KA_TRACE( 20, ("__kmp_register_root: T#%d init T#%d(%d:%d) arrived: join=%u, plain=%u\n", gtid, __kmp_gtid_from_tid( 0, root->r.r_hot_team ), diff --git a/openmp/runtime/src/z_Linux_util.c b/openmp/runtime/src/z_Linux_util.c index 16fc1c9ce98f..1e7683d2402a 100644 --- a/openmp/runtime/src/z_Linux_util.c +++ b/openmp/runtime/src/z_Linux_util.c @@ -1897,18 +1897,21 @@ __kmp_yield( int cond ) void __kmp_gtid_set_specific( int gtid ) { - int status; - KMP_ASSERT( __kmp_init_runtime ); - status = pthread_setspecific( __kmp_gtid_threadprivate_key, (void*)(intptr_t)(gtid+1) ); - KMP_CHECK_SYSFAIL( "pthread_setspecific", status ); + if( __kmp_init_gtid ) { + int status; + status = pthread_setspecific( __kmp_gtid_threadprivate_key, (void*)(intptr_t)(gtid+1) ); + KMP_CHECK_SYSFAIL( "pthread_setspecific", status ); + } else { + KA_TRACE( 50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n" ) ); + } } int __kmp_gtid_get_specific() { int gtid; - if ( !__kmp_init_runtime ) { - KA_TRACE( 50, ("__kmp_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) ); + if ( !__kmp_init_gtid ) { + KA_TRACE( 50, ("__kmp_gtid_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) ); return KMP_GTID_SHUTDOWN; } gtid = (int)(size_t)pthread_getspecific( __kmp_gtid_threadprivate_key ); diff --git a/openmp/runtime/src/z_Windows_NT_util.c b/openmp/runtime/src/z_Windows_NT_util.c index 5e1424089b16..0191352c8a2f 100644 --- a/openmp/runtime/src/z_Windows_NT_util.c +++ b/openmp/runtime/src/z_Windows_NT_util.c @@ -507,19 +507,22 @@ __kmp_yield( int cond ) void __kmp_gtid_set_specific( int gtid ) { - KA_TRACE( 50, ("__kmp_gtid_set_specific: T#%d key:%d\n", - gtid, __kmp_gtid_threadprivate_key )); - KMP_ASSERT( __kmp_init_runtime ); - if( ! TlsSetValue( __kmp_gtid_threadprivate_key, (LPVOID)(gtid+1)) ) - KMP_FATAL( TLSSetValueFailed ); + if( __kmp_init_gtid ) { + KA_TRACE( 50, ("__kmp_gtid_set_specific: T#%d key:%d\n", + gtid, __kmp_gtid_threadprivate_key )); + if( ! TlsSetValue( __kmp_gtid_threadprivate_key, (LPVOID)(gtid+1)) ) + KMP_FATAL( TLSSetValueFailed ); + } else { + KA_TRACE( 50, ("__kmp_gtid_set_specific: runtime shutdown, returning\n" ) ); + } } int __kmp_gtid_get_specific() { int gtid; - if( !__kmp_init_runtime ) { - KA_TRACE( 50, ("__kmp_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) ); + if( !__kmp_init_gtid ) { + KA_TRACE( 50, ("__kmp_gtid_get_specific: runtime shutdown, returning KMP_GTID_SHUTDOWN\n" ) ); return KMP_GTID_SHUTDOWN; } gtid = (int)(kmp_intptr_t)TlsGetValue( __kmp_gtid_threadprivate_key );