Bug 757969 - use __thread in ThreadLocal; r=froydnj

This commit is contained in:
Tom Tromey 2015-11-23 12:11:22 -07:00
parent 7bff6c515d
commit 5412728905
22 changed files with 124 additions and 77 deletions

View File

@ -26,7 +26,8 @@
namespace mozilla {
namespace dom {
static mozilla::ThreadLocal<ScriptSettingsStackEntry*> sScriptSettingsTLS;
static MOZ_THREAD_LOCAL(ScriptSettingsStackEntry*) sScriptSettingsTLS;
static bool sScriptSettingsTLSInitialized;
class ScriptSettingsStack {
public:
@ -94,14 +95,13 @@ UnuseEntryScriptProfiling()
void
InitScriptSettings()
{
if (!sScriptSettingsTLS.initialized()) {
bool success = sScriptSettingsTLS.init();
if (!success) {
MOZ_CRASH();
}
bool success = sScriptSettingsTLS.init();
if (!success) {
MOZ_CRASH();
}
sScriptSettingsTLS.set(nullptr);
sScriptSettingsTLSInitialized = true;
}
void
@ -113,7 +113,7 @@ DestroyScriptSettings()
bool
ScriptSettingsInitialized()
{
return sScriptSettingsTLS.initialized();
return sScriptSettingsTLSInitialized;
}
ScriptSettingsStackEntry::ScriptSettingsStackEntry(nsIGlobalObject *aGlobal,

View File

@ -60,10 +60,10 @@ public:
private:
// `true` if an instance of `FlushRejections` is currently dispatched
// and has not been executed yet.
static ThreadLocal<bool> sDispatched;
static MOZ_THREAD_LOCAL(bool) sDispatched;
};
/* static */ ThreadLocal<bool>
/* static */ MOZ_THREAD_LOCAL(bool)
FlushRejections::sDispatched;
static Promise*

View File

@ -29,7 +29,7 @@ namespace gl {
StaticMutex GLLibraryEGL::sMutex;
GLLibraryEGL sEGLLibrary;
#ifdef MOZ_B2G
ThreadLocal<EGLContext> GLLibraryEGL::sCurrentContext;
MOZ_THREAD_LOCAL(EGLContext) GLLibraryEGL::sCurrentContext;
#endif
// should match the order of EGLExtensions, and be null-terminated.

View File

@ -641,7 +641,7 @@ public:
}
private:
static ThreadLocal<EGLContext> sCurrentContext;
static MOZ_THREAD_LOCAL(EGLContext) sCurrentContext;
public:
#else

View File

@ -24,16 +24,14 @@ using mozilla::gl::GLFeature;
using mozilla::gl::SkiaGLGlue;
using mozilla::gfx::DrawTarget;
static mozilla::ThreadLocal<GLContext*> sGLContext;
static MOZ_THREAD_LOCAL(GLContext*) sGLContext;
extern "C" {
static void SetStaticGLContext(GLContext* context)
{
if (!sGLContext.initialized()) {
mozilla::DebugOnly<bool> success = sGLContext.init();
MOZ_ASSERT(success);
}
mozilla::DebugOnly<bool> success = sGLContext.init();
MOZ_ASSERT(success);
sGLContext.set(context);
}

View File

@ -58,17 +58,15 @@
using namespace js;
using namespace js::jit;
using mozilla::ThreadLocal;
// Assert that JitCode is gc::Cell aligned.
JS_STATIC_ASSERT(sizeof(JitCode) % gc::CellSize == 0);
static ThreadLocal<JitContext*> TlsJitContext;
static MOZ_THREAD_LOCAL(JitContext*) TlsJitContext;
static JitContext*
CurrentJitContext()
{
if (!TlsJitContext.initialized())
if (!TlsJitContext.init())
return nullptr;
return TlsJitContext.get();
}
@ -155,7 +153,7 @@ JitContext::~JitContext()
bool
jit::InitializeIon()
{
if (!TlsJitContext.initialized() && !TlsJitContext.init())
if (!TlsJitContext.init())
return false;
CheckLogging();
#if defined(JS_CODEGEN_ARM)

View File

@ -37,11 +37,11 @@ namespace js {
namespace oom {
JS_PUBLIC_DATA(uint32_t) targetThread = 0;
JS_PUBLIC_DATA(mozilla::ThreadLocal<uint32_t>) threadType;
JS_PUBLIC_DATA(MOZ_THREAD_LOCAL(uint32_t)) threadType;
bool
InitThreadType(void) {
return threadType.initialized() || threadType.init();
return threadType.init();
}
void

View File

@ -75,7 +75,7 @@ JS_Init(void)
#endif
using js::TlsPerThreadData;
if (!TlsPerThreadData.initialized() && !TlsPerThreadData.init())
if (!TlsPerThreadData.init())
return false;
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)

View File

@ -63,11 +63,10 @@ using mozilla::NegativeInfinity;
using mozilla::PodZero;
using mozilla::PodArrayZero;
using mozilla::PositiveInfinity;
using mozilla::ThreadLocal;
using JS::GenericNaN;
using JS::DoubleNaNValue;
/* static */ ThreadLocal<PerThreadData*> js::TlsPerThreadData;
/* static */ MOZ_THREAD_LOCAL(PerThreadData*) js::TlsPerThreadData;
/* static */ Atomic<size_t> JSRuntime::liveRuntimesCount;
namespace js {

View File

@ -63,7 +63,7 @@ class TraceLoggerThread;
#endif
/* Thread Local Storage slot for storing the runtime for a thread. */
extern mozilla::ThreadLocal<PerThreadData*> TlsPerThreadData;
extern MOZ_THREAD_LOCAL(PerThreadData*) TlsPerThreadData;
} // namespace js

View File

@ -42,11 +42,28 @@ typedef unsigned long sig_safe_t;
typedef sig_atomic_t sig_safe_t;
#endif
namespace detail {
#if defined(HAVE_THREAD_TLS_KEYWORD)
#define MOZ_HAS_THREAD_LOCAL
#endif
/*
* Thread Local Storage helpers.
*
* Usage:
*
* Do not directly instantiate this class. Instead, use the
* MOZ_THREAD_LOCAL macro to declare or define instances. The macro
* takes a type name as its argument.
*
* Declare like this:
* extern MOZ_THREAD_LOCAL(int) tlsInt;
* Define like this:
* MOZ_THREAD_LOCAL(int) tlsInt;
* or:
* static MOZ_THREAD_LOCAL(int) tlsInt;
*
* Only static-storage-duration (e.g. global variables, or static class members)
* objects of this class should be instantiated. This class relies on
* zero-initialization, which is implicit for static-storage-duration objects.
@ -56,9 +73,10 @@ typedef sig_atomic_t sig_safe_t;
*
* // Create a TLS item.
* //
* // Note that init() should be invoked exactly once, before any usage of set()
* // or get().
* mozilla::ThreadLocal<int> tlsKey;
* // Note that init() should be invoked before the first use of set()
* // or get(). It is ok to call it multiple times. This must be
* // called in a way that avoids possible races with other threads.
* MOZ_THREAD_LOCAL(int) tlsKey;
* if (!tlsKey.init()) {
* // deal with the error
* }
@ -72,6 +90,7 @@ typedef sig_atomic_t sig_safe_t;
template<typename T>
class ThreadLocal
{
#ifndef MOZ_HAS_THREAD_LOCAL
#if defined(XP_WIN)
typedef unsigned long key_t;
#else
@ -93,11 +112,24 @@ class ThreadLocal
{
typedef S *Type;
};
#endif
bool initialized() const {
#ifdef MOZ_HAS_THREAD_LOCAL
return true;
#else
return mInited;
#endif
}
public:
// __thread does not allow non-trivial constructors, but we can
// instead rely on zero-initialization.
#ifndef MOZ_HAS_THREAD_LOCAL
ThreadLocal()
: mKey(0), mInited(false)
{}
#endif
MOZ_WARN_UNUSED_RESULT inline bool init();
@ -105,11 +137,13 @@ public:
inline void set(const T aValue);
bool initialized() const { return mInited; }
private:
#ifdef MOZ_HAS_THREAD_LOCAL
T mValue;
#else
key_t mKey;
bool mInited;
#endif
};
template<typename T>
@ -122,20 +156,29 @@ ThreadLocal<T>::init()
static_assert(sizeof(T) <= sizeof(void*),
"mozilla::ThreadLocal can't be used for types larger than "
"a pointer");
MOZ_ASSERT(!initialized());
#ifdef XP_WIN
mKey = TlsAlloc();
mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
#ifdef MOZ_HAS_THREAD_LOCAL
return true;
#else
mInited = !pthread_key_create(&mKey, nullptr);
if (!initialized()) {
#ifdef XP_WIN
mKey = TlsAlloc();
mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
#else
mInited = !pthread_key_create(&mKey, nullptr);
#endif
}
return mInited;
#endif
}
template<typename T>
inline T
ThreadLocal<T>::get() const
{
#ifdef MOZ_HAS_THREAD_LOCAL
return mValue;
#else
MOZ_ASSERT(initialized());
void* h;
#ifdef XP_WIN
@ -144,12 +187,16 @@ ThreadLocal<T>::get() const
h = pthread_getspecific(mKey);
#endif
return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
#endif
}
template<typename T>
inline void
ThreadLocal<T>::set(const T aValue)
{
#ifdef MOZ_HAS_THREAD_LOCAL
mValue = aValue;
#else
MOZ_ASSERT(initialized());
void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
#ifdef XP_WIN
@ -160,8 +207,16 @@ ThreadLocal<T>::set(const T aValue)
if (!succeeded) {
MOZ_CRASH();
}
#endif
}
#ifdef MOZ_HAS_THREAD_LOCAL
#define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE>
#else
#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
#endif
} // namespace detail
} // namespace mozilla
#endif /* mozilla_ThreadLocal_h */

View File

@ -20,7 +20,7 @@
namespace mozilla {
#ifdef MOZ_REPLACE_MALLOC
ThreadLocal<bool> MallocHook::mEnabledTLS;
MOZ_THREAD_LOCAL(bool) MallocHook::mEnabledTLS;
NativeProfiler* MallocHook::mNativeProfiler;
malloc_hook_table_t MallocHook::mMallocHook;
#endif
@ -81,12 +81,10 @@ MallocHook::Initialize()
if (bridge) {
mozilla::Unused << bridge->RegisterHook("memory-profiler", nullptr, nullptr);
}
if (!mEnabledTLS.initialized()) {
bool success = mEnabledTLS.init();
if (NS_WARN_IF(!success)) {
return;
}
mEnabledTLS.set(false);
bool success = mEnabledTLS.init();
if (NS_WARN_IF(!success)) {
return;
}
#endif
}
@ -96,9 +94,6 @@ MallocHook::Enable(NativeProfiler* aNativeProfiler)
{
#ifdef MOZ_REPLACE_MALLOC
MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(!mEnabledTLS.initialized())) {
return;
}
ReplaceMallocBridge* bridge = ReplaceMallocBridge::Get(3);
if (bridge) {
const malloc_table_t* alloc_funcs =

View File

@ -29,7 +29,7 @@ private:
static void* SampleNative(void* aAddr, size_t aSize);
static void RemoveNative(void* aAddr);
#ifdef MOZ_REPLACE_MALLOC
static ThreadLocal<bool> mEnabledTLS;
static MOZ_THREAD_LOCAL(bool) mEnabledTLS;
static NativeProfiler* mNativeProfiler;
static malloc_hook_table_t mMallocHook;
#endif

View File

@ -67,9 +67,9 @@ public:
};
#endif
mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
mozilla::ThreadLocal<GeckoSampler *> tlsTicker;
mozilla::ThreadLocal<void *> tlsStackTop;
MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
MOZ_THREAD_LOCAL(GeckoSampler *) tlsTicker;
MOZ_THREAD_LOCAL(void *) tlsStackTop;
// We need to track whether we've been initialized otherwise
// we end up using tlsStack without initializing it.
// Because tlsStack is totally opaque to us we can't reuse

View File

@ -40,9 +40,9 @@ namespace mozilla {
class TimeStamp;
} // namespace mozilla
extern mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
extern mozilla::ThreadLocal<GeckoSampler *> tlsTicker;
extern mozilla::ThreadLocal<void *> tlsStackTop;
extern MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack;
extern MOZ_THREAD_LOCAL(GeckoSampler *) tlsTicker;
extern MOZ_THREAD_LOCAL(void *) tlsStackTop;
extern bool stack_key_initialized;
#ifndef SAMPLE_FUNCTION_NAME

View File

@ -59,7 +59,7 @@ pid_t gettid();
namespace mozilla {
namespace tasktracer {
static mozilla::ThreadLocal<TraceInfo*> sTraceInfoTLS;
static MOZ_THREAD_LOCAL(TraceInfo*) sTraceInfoTLS;
static mozilla::StaticMutex sMutex;
// The generation of TraceInfo. It will be > 0 if the Task Tracer is started and

View File

@ -1409,7 +1409,7 @@ struct CollectorData
CycleCollectedJSRuntime* mRuntime;
};
static mozilla::ThreadLocal<CollectorData*> sCollectorData;
static MOZ_THREAD_LOCAL(CollectorData*) sCollectorData;
////////////////////////////////////////////////////////////////////////
// Utility functions
@ -3999,8 +3999,11 @@ nsCycleCollector_suspectedCount()
bool
nsCycleCollector_init()
{
static DebugOnly<bool> sInitialized;
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
MOZ_ASSERT(!sCollectorData.initialized(), "Called twice!?");
MOZ_ASSERT(!sInitialized, "Called twice!?");
sInitialized = true;
return sCollectorData.init();
}
@ -4008,8 +4011,6 @@ nsCycleCollector_init()
void
nsCycleCollector_startup()
{
MOZ_ASSERT(sCollectorData.initialized(),
"Forgot to call nsCycleCollector_init!");
if (sCollectorData.get()) {
MOZ_CRASH();
}

View File

@ -359,7 +359,8 @@ public:
// List of observers registered
static StaticAutoPtr<MasterList> sMasterList;
static ThreadLocal<PerThreadData*> sThreadLocalData;
static MOZ_THREAD_LOCAL(PerThreadData*) sThreadLocalData;
static bool sThreadLocalDataInitialized;
} // namespace
IOInterposeObserver::Observation::Observation(Operation aOperation,
@ -429,6 +430,7 @@ IOInterposer::Init()
if (!sThreadLocalData.init()) {
return false;
}
sThreadLocalDataInitialized = true;
bool isMainThread = true;
RegisterCurrentThread(isMainThread);
sMasterList = new MasterList();
@ -448,7 +450,7 @@ IOInterposer::Init()
bool
IOInterposeObserver::IsMainThread()
{
if (!sThreadLocalData.initialized()) {
if (!sThreadLocalDataInitialized) {
return false;
}
PerThreadData* ptd = sThreadLocalData.get();
@ -538,7 +540,7 @@ IOInterposer::Unregister(IOInterposeObserver::Operation aOp,
void
IOInterposer::RegisterCurrentThread(bool aIsMainThread)
{
if (!sThreadLocalData.initialized()) {
if (!sThreadLocalDataInitialized) {
return;
}
MOZ_ASSERT(!sThreadLocalData.get());
@ -549,7 +551,7 @@ IOInterposer::RegisterCurrentThread(bool aIsMainThread)
void
IOInterposer::UnregisterCurrentThread()
{
if (!sThreadLocalData.initialized()) {
if (!sThreadLocalDataInitialized) {
return;
}
PerThreadData* curThreadData = sThreadLocalData.get();

View File

@ -26,7 +26,7 @@ LazyLogModule gMozPromiseLog("MozPromise");
LazyLogModule gStateWatchingLog("StateWatching");
StaticRefPtr<AbstractThread> sMainThread;
ThreadLocal<AbstractThread*> AbstractThread::sCurrentThreadTLS;
MOZ_THREAD_LOCAL(AbstractThread*) AbstractThread::sCurrentThreadTLS;
class XPCOMThreadWrapper : public AbstractThread
{

View File

@ -85,7 +85,7 @@ public:
protected:
virtual ~AbstractThread() {}
static ThreadLocal<AbstractThread*> sCurrentThreadTLS;
static MOZ_THREAD_LOCAL(AbstractThread*) sCurrentThreadTLS;
// True if we want to require that every task dispatched from tasks running in
// this queue go through our queue's tail dispatcher.

View File

@ -138,7 +138,8 @@ BackgroundHangManager::Observe(nsISupports* aSubject, const char* aTopic, const
class BackgroundHangThread : public LinkedListElement<BackgroundHangThread>
{
private:
static ThreadLocal<BackgroundHangThread*> sTlsKey;
static MOZ_THREAD_LOCAL(BackgroundHangThread*) sTlsKey;
static bool sTlsKeyInitialized;
BackgroundHangThread(const BackgroundHangThread&);
BackgroundHangThread& operator=(const BackgroundHangThread&);
@ -206,8 +207,8 @@ StaticRefPtr<BackgroundHangManager> BackgroundHangManager::sInstance;
bool BackgroundHangManager::sProhibited = false;
bool BackgroundHangManager::sDisabled = false;
ThreadLocal<BackgroundHangThread*> BackgroundHangThread::sTlsKey;
MOZ_THREAD_LOCAL(BackgroundHangThread*) BackgroundHangThread::sTlsKey;
bool BackgroundHangThread::sTlsKeyInitialized;
BackgroundHangManager::BackgroundHangManager()
: mShutdown(false)
@ -372,7 +373,7 @@ BackgroundHangThread::BackgroundHangThread(const char* aName,
, mWaiting(true)
, mStats(aName)
{
if (sTlsKey.initialized()) {
if (sTlsKeyInitialized) {
sTlsKey.set(this);
}
// Lock here because LinkedList is not thread-safe
@ -393,7 +394,7 @@ BackgroundHangThread::~BackgroundHangThread()
autoLock.Notify();
// We no longer have a thread
if (sTlsKey.initialized()) {
if (sTlsKeyInitialized) {
sTlsKey.set(nullptr);
}
@ -489,7 +490,7 @@ BackgroundHangThread::FindThread()
return nullptr;
}
if (sTlsKey.initialized()) {
if (sTlsKeyInitialized) {
// Use TLS if available
MOZ_ASSERT(!BackgroundHangManager::sProhibited,
"BackgroundHandleManager is not initialized");

View File

@ -18,7 +18,7 @@
using namespace mozilla;
static mozilla::ThreadLocal<bool> sTLSIsMainThread;
static MOZ_THREAD_LOCAL(bool) sTLSIsMainThread;
bool
NS_IsMainThread()
@ -29,12 +29,10 @@ NS_IsMainThread()
void
NS_SetMainThread()
{
if (!sTLSIsMainThread.initialized()) {
if (!sTLSIsMainThread.init()) {
MOZ_CRASH();
}
sTLSIsMainThread.set(true);
if (!sTLSIsMainThread.init()) {
MOZ_CRASH();
}
sTLSIsMainThread.set(true);
MOZ_ASSERT(NS_IsMainThread());
}