Make NS_IsMainThread faster on our major platforms. (Bug 521750) r=dbaron a1.9.1.5=dveditz/ss
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 28 Oct 2009 10:28:57 -0700
changeset 26508 ce53b1c742c38f691ae17e6949abcd39010b7469
parent 26507 b3078ea110413d338680bc759ac27a6806729b0e
child 26509 0ecb15e3abbe255e9ab94fe8e05252c5448bd347
push id2072
push userdbaron@mozilla.com
push dateFri, 30 Oct 2009 22:07:29 +0000
reviewersdbaron
bugs521750
milestone1.9.1.5pre
Make NS_IsMainThread faster on our major platforms. (Bug 521750) r=dbaron a1.9.1.5=dveditz/ss
configure.in
xpcom/base/nscore.h
xpcom/glue/nsThreadUtils.cpp
xpcom/glue/nsThreadUtils.h
xpcom/threads/nsThreadManager.cpp
--- a/configure.in
+++ b/configure.in
@@ -3998,17 +3998,25 @@ AC_CACHE_CHECK(for trouble comparing to 
                                 template <class T> int operator!=(const T2*, const T&) { return 0; }],
                                [Foo<int> f; return (0 != f);],
                                ac_cv_trouble_comparing_to_zero=no,
                                ac_cv_trouble_comparing_to_zero=yes)])
 if test "$ac_cv_trouble_comparing_to_zero" = yes ; then
   AC_DEFINE(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
 fi
 
-
+AC_CACHE_CHECK(for __thread keyword for TLS variables,
+               ac_cv_thread_keyword,
+               [AC_TRY_LINK([__thread bool tlsIsMainThread = false;],
+                            [return tlsIsMainThread;],
+                            ac_cv_thread_keyword=yes,
+                            ac_cv_thread_keyword=no)])
+if test "$ac_cv_thread_keyword" = yes; then
+  AC_DEFINE(HAVE_THREAD_TLS_KEYWORD)
+fi
 
 dnl End of C++ language/feature checks
 AC_LANG_C
 
 dnl ========================================================
 dnl =  Internationalization checks
 dnl ========================================================
 dnl
--- a/xpcom/base/nscore.h
+++ b/xpcom/base/nscore.h
@@ -473,16 +473,22 @@ typedef PRUint32 nsrefcnt;
   * If we're being linked as standalone glue, we don't want a dynamic dependency
   * on NSPR libs, so we skip the debug thread-safety checks, and we cannot use
   * the THREADSAFE_ISUPPORTS macros.
   */
 #if defined(XPCOM_GLUE) && !defined(XPCOM_GLUE_USE_NSPR)
 #define XPCOM_GLUE_AVOID_NSPR
 #endif
 
+#if defined(_MSC_VER) && !defined(WINCE)
+#define NS_TLS __declspec(thread)
+#elif defined(HAVE_THREAD_TLS_KEYWORD)
+#define NS_TLS __thread
+#endif
+
 /**
  * Static type annotations, enforced when static-checking is enabled:
  *
  * NS_STACK_CLASS: a class which must only be instantiated on the stack
  * NS_FINAL_CLASS: a class which may not be subclassed
  */
 #ifdef NS_STATIC_CHECKING
 #define NS_STACK_CLASS __attribute__((user("NS_stack")))
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -111,30 +111,39 @@ NS_GetMainThread(nsIThread **result)
   nsresult rv;
   nsCOMPtr<nsIThreadManager> mgr =
       do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   return mgr->GetMainThread(result);
 #endif
 }
 
-NS_METHOD_(PRBool)
-NS_IsMainThread()
+#ifndef MOZILLA_INTERNAL_API
+bool NS_IsMainThread()
 {
   PRBool result = PR_FALSE;
-#ifdef MOZILLA_INTERNAL_API
-  nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result);
-#else
   nsCOMPtr<nsIThreadManager> mgr =
-      do_GetService(NS_THREADMANAGER_CONTRACTID);
+    do_GetService(NS_THREADMANAGER_CONTRACTID);
   if (mgr)
     mgr->GetIsMainThread(&result);
+  return bool(result);
+}
+#elif !defined(NS_TLS)
+bool NS_IsMainThread()
+{
+  PRBool result = PR_FALSE;
+  nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result);
+  return bool(result);
+}
+#elif !defined(MOZ_ENABLE_LIBXUL)
+bool NS_IsMainThread()
+{
+  return gTLSIsMainThread;
+}
 #endif
-  return result;
-}
 
 NS_METHOD
 NS_DispatchToCurrentThread(nsIRunnable *event)
 {
 #ifdef MOZILLA_INTERNAL_API
   nsIThread *thread = NS_GetCurrentThread();
   if (!thread) { return NS_ERROR_UNEXPECTED; }
 #else
--- a/xpcom/glue/nsThreadUtils.h
+++ b/xpcom/glue/nsThreadUtils.h
@@ -93,24 +93,38 @@ NS_GetCurrentThread(nsIThread **result);
  * Get a reference to the main thread.
  *
  * @param result
  *   The resulting nsIThread object.
  */
 extern NS_COM_GLUE NS_METHOD
 NS_GetMainThread(nsIThread **result);
 
+#if defined(MOZILLA_INTERNAL_API) && defined(NS_TLS)
+// This is defined in nsThreadManager.cpp and initialized to `true` for the
+// main thread by nsThreadManager::Init.
+extern NS_TLS bool gTLSIsMainThread;
+
+#ifdef MOZ_ENABLE_LIBXUL
+inline bool NS_IsMainThread()
+{
+  return gTLSIsMainThread;
+}
+#else
+NS_COM bool NS_IsMainThread();
+#endif
+#else
 /**
  * Test to see if the current thread is the main thread.
  *
  * @returns PR_TRUE if the current thread is the main thread, and PR_FALSE
  * otherwise.
  */
-extern NS_COM_GLUE NS_METHOD_(PRBool)
-NS_IsMainThread();
+extern NS_COM_GLUE bool NS_IsMainThread();
+#endif
 
 /**
  * Dispatch the given event to the current thread.
  *
  * @param event
  *   The event to dispatch.
  *
  * @returns NS_ERROR_INVALID_ARG
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -33,21 +33,26 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsThreadManager.h"
 #include "nsThread.h"
+#include "nsThreadUtils.h"
 #include "nsIClassInfoImpl.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "nsAutoLock.h"
 
+#ifdef NS_TLS
+NS_TLS bool gTLSIsMainThread = false;
+#endif
+
 typedef nsTArray< nsRefPtr<nsThread> > nsThreadArray;
 
 //-----------------------------------------------------------------------------
 
 static void
 ReleaseObject(void *data)
 {
   static_cast<nsISupports *>(data)->Release();
@@ -96,16 +101,20 @@ nsThreadManager::Init()
     mMainThread = nsnull;
     return rv;
   }
 
   // We need to keep a pointer to the current thread, so we can satisfy
   // GetIsMainThread calls that occur post-Shutdown.
   mMainThread->GetPRThread(&mMainPRThread);
 
+#ifdef NS_TLS
+  gTLSIsMainThread = true;
+#endif
+
   mInitialized = PR_TRUE;
   return NS_OK;
 }
 
 void
 nsThreadManager::Shutdown()
 {
   NS_ASSERTION(NS_IsMainThread(), "shutdown not called from main thread");