Bug 1033358 - Make NS_IsMainThread use its own TLS so it's always correct, from early init to exit time - r=bsmedberg
☠☠ backed out by 1fd5a864e81d ☠ ☠
authorBenoit Jacob <bjacob@mozilla.com>
Thu, 03 Jul 2014 14:53:24 -0400
changeset 192174 7829c78348a4429a8362c0953ecf66d398fc8e95
parent 192173 c571df9a85de14c34bab14c1bcd48303a326cb86
child 192175 719844108f1a3cf1b6de996162c499f04219fa93
push id45776
push userbjacob@mozilla.com
push dateThu, 03 Jul 2014 18:57:18 +0000
treeherdermozilla-inbound@a54b05c9e4a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg
bugs1033358
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1033358 - Make NS_IsMainThread use its own TLS so it's always correct, from early init to exit time - r=bsmedberg
xpcom/base/nsTraceRefcnt.cpp
xpcom/glue/MainThreadUtils.h
xpcom/glue/nsThreadUtils.cpp
xpcom/glue/nsThreadUtils.h
xpcom/threads/nsThreadManager.cpp
--- a/xpcom/base/nsTraceRefcnt.cpp
+++ b/xpcom/base/nsTraceRefcnt.cpp
@@ -13,16 +13,17 @@
 #include "prenv.h"
 #include "plstr.h"
 #include "prlink.h"
 #include "nsCRT.h"
 #include <math.h>
 #include "nsStackWalkPrivate.h"
 #include "nsStackWalk.h"
 #include "nsString.h"
+#include "nsThreadUtils.h"
 
 #include "nsXULAppAPI.h"
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #else
 #include <unistd.h>
 #endif
@@ -914,16 +915,18 @@ nsTraceRefcnt::DemangleSymbol(const char
 }
 
 
 //----------------------------------------------------------------------
 
 EXPORT_XPCOM_API(void)
 NS_LogInit()
 {
+  NS_SetMainThread();
+
   // FIXME: This is called multiple times, we should probably not allow that.
 #ifdef STACKWALKING_AVAILABLE
   StackWalkInitCriticalAddress();
 #endif
 #ifdef NS_IMPL_REFCNT_LOGGING
   if (++gInitCount) {
     nsTraceRefcnt::SetActivityIsLegal(true);
   }
--- a/xpcom/glue/MainThreadUtils.h
+++ b/xpcom/glue/MainThreadUtils.h
@@ -23,31 +23,18 @@ extern NS_COM_GLUE NS_METHOD NS_GetMainT
 #ifdef MOZILLA_INTERNAL_API
 // Fast access to the current thread.  Do not release the returned pointer!  If
 // you want to use this pointer from some other thread, then you will need to
 // AddRef it.  Otherwise, you should only consider this pointer valid from code
 // running on the current thread.
 extern NS_COM_GLUE nsIThread* NS_GetCurrentThread();
 #endif
 
-#if defined(MOZILLA_INTERNAL_API) && defined(XP_WIN)
+#ifdef MOZILLA_INTERNAL_API
 bool NS_IsMainThread();
-#elif defined(MOZILLA_INTERNAL_API) && defined(NS_TLS)
-// This is defined in nsThreadManager.cpp and initialized to `Main` for the
-// main thread by nsThreadManager::Init.
-extern NS_TLS mozilla::threads::ID gTLSThreadID;
-#ifdef MOZ_ASAN
-// Temporary workaround, see bug 895845
-MOZ_ASAN_BLACKLIST bool NS_IsMainThread();
-#else
-inline bool NS_IsMainThread()
-{
-  return gTLSThreadID == mozilla::threads::Main;
-}
-#endif
 #else
 /**
  * Test to see if the current thread is the main thread.
  *
  * @returns true if the current thread is the main thread, and false
  * otherwise.
  */
 extern NS_COM_GLUE bool NS_IsMainThread();
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -120,57 +120,29 @@ NS_GetMainThread(nsIThread** aResult)
     do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
   return mgr->GetMainThread(aResult);
 #endif
 }
 
-#if defined(MOZILLA_INTERNAL_API) && defined(XP_WIN)
-extern DWORD gTLSThreadIDIndex;
-bool
-NS_IsMainThread()
-{
-  return TlsGetValue(gTLSThreadIDIndex) == (void*)mozilla::threads::Main;
-}
-#elif defined(MOZILLA_INTERNAL_API) && defined(NS_TLS)
-#ifdef MOZ_ASAN
-// Temporary workaround, see bug 895845
-bool
-NS_IsMainThread()
-{
-  return gTLSThreadID == mozilla::threads::Main;
-}
-#else
-// NS_IsMainThread() is defined inline in MainThreadUtils.h
-#endif
-#else
-#ifdef MOZILLA_INTERNAL_API
-bool
-NS_IsMainThread()
-{
-  bool result = false;
-  nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result);
-  return bool(result);
-}
-#else
+#ifndef MOZILLA_INTERNAL_API
 bool
 NS_IsMainThread()
 {
   bool result = false;
   nsCOMPtr<nsIThreadManager> mgr =
     do_GetService(NS_THREADMANAGER_CONTRACTID);
   if (mgr) {
     mgr->GetIsMainThread(&result);
   }
   return bool(result);
 }
 #endif
-#endif
 
 NS_METHOD
 NS_DispatchToCurrentThread(nsIRunnable* aEvent)
 {
 #ifdef MOZILLA_INTERNAL_API
   nsIThread* thread = NS_GetCurrentThread();
   if (!thread) {
     return NS_ERROR_UNEXPECTED;
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -560,11 +560,12 @@ public:
 
 private:
   bool lowIOPrioritySet;
 #if defined(XP_MACOSX)
   int oldPriority;
 #endif
 };
 
-
+void
+NS_SetMainThread();
 
 #endif  // nsThreadUtils_h__
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -5,30 +5,51 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsThreadManager.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
+#include "mozilla/ThreadLocal.h"
 #ifdef MOZ_CANARY
 #include <fcntl.h>
 #include <unistd.h>
 #endif
 
 using namespace mozilla;
 
 #ifdef XP_WIN
 #include <windows.h>
 DWORD gTLSThreadIDIndex = TlsAlloc();
 #elif defined(NS_TLS)
 NS_TLS mozilla::threads::ID gTLSThreadID = mozilla::threads::Generic;
 #endif
 
+static mozilla::ThreadLocal<bool> sTLSIsMainThread;
+
+bool
+NS_IsMainThread()
+{
+  return sTLSIsMainThread.get();
+}
+
+void
+NS_SetMainThread()
+{
+  if (!sTLSIsMainThread.initialized()) {
+    if (!sTLSIsMainThread.init()) {
+      MOZ_CRASH();
+    }
+    sTLSIsMainThread.set(true);
+  }
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
 typedef nsTArray<nsRefPtr<nsThread>> nsThreadArray;
 
 //-----------------------------------------------------------------------------
 
 static void
 ReleaseObject(void* aData)
 {
   static_cast<nsISupports*>(aData)->Release();