Commit d8bd57dd authored by Jeremy Roman's avatar Jeremy Roman Committed by Commit Bot

WTF: Merge common logic from threading_pthreads and threading_win.

Much of this code is essentially identical. What remains different is just
a couple syscalls (of which there are many variations in threading_pthreads
already), and the implementations of mutexes and condition variables, which
we hope to remove soon (and so have been left where they are).

Bug: 856641
Change-Id: I7c658a0fe65fb6a3428ff4b215397da410d2233a
Reviewed-on: https://chromium-review.googlesource.com/1195713
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#587334}
parent 3aeb4361
...@@ -200,6 +200,7 @@ jumbo_component("wtf") { ...@@ -200,6 +200,7 @@ jumbo_component("wtf") {
"thread_restriction_verifier.h", "thread_restriction_verifier.h",
"thread_safe_ref_counted.h", "thread_safe_ref_counted.h",
"thread_specific.h", "thread_specific.h",
"threading.cc",
"threading.h", "threading.h",
"threading_primitives.h", "threading_primitives.h",
"threading_pthreads.cc", "threading_pthreads.cc",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/platform/wtf/threading.h"
#include "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h"
#include "third_party/blink/renderer/platform/wtf/wtf_thread_data.h"
#if defined(OS_WIN)
#include <windows.h>
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
#include <pthread.h>
#else
#error Blink does not support threading on your platform.
#endif
#if defined(OS_LINUX)
#include <sys/syscall.h>
#elif defined(OS_ANDROID)
#include <sys/types.h>
#endif
namespace WTF {
// Current thread identity
namespace internal {
ThreadIdentifier CurrentThreadSyscall() {
#if defined(OS_WIN)
return static_cast<ThreadIdentifier>(GetCurrentThreadId());
#elif defined(OS_MACOSX)
return pthread_mach_thread_np(pthread_self());
#elif defined(OS_LINUX)
return syscall(__NR_gettid);
#elif defined(OS_ANDROID)
return gettid();
#else
return reinterpret_cast<uintptr_t>(pthread_self());
#endif
}
} // namespace internal
namespace {
bool g_current_thread_key_initialized = false;
#if defined(OS_WIN)
DWORD g_current_thread_key;
void RawCurrentThreadInit() {
g_current_thread_key = ::TlsAlloc();
CHECK_NE(g_current_thread_key, TLS_OUT_OF_INDEXES);
}
void* RawCurrentThreadGet() {
return ::TlsGetValue(g_current_thread_key);
}
void RawCurrentThreadSet(void* value) {
::TlsSetValue(g_current_thread_key, value);
}
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
pthread_key_t g_current_thread_key;
void RawCurrentThreadInit() {
int error = pthread_key_create(&g_current_thread_key, nullptr);
CHECK(!error);
}
void* RawCurrentThreadGet() {
return pthread_getspecific(g_current_thread_key);
}
void RawCurrentThreadSet(void* value) {
pthread_setspecific(g_current_thread_key, value);
}
#endif
} // namespace
void InitializeCurrentThread() {
DCHECK(!g_current_thread_key_initialized);
RawCurrentThreadInit();
g_current_thread_key_initialized = true;
}
ThreadIdentifier CurrentThread() {
// This doesn't use WTF::ThreadSpecific (e.g. WTFThreadData) because
// ThreadSpecific now depends on currentThread. It is necessary to avoid this
// or a similar loop:
//
// CurrentThread
// -> WtfThreadData
// -> ThreadSpecific::operator*
// -> IsMainThread
// -> CurrentThread
static_assert(sizeof(ThreadIdentifier) <= sizeof(void*),
"ThreadIdentifier must fit in a void*.");
DCHECK(g_current_thread_key_initialized);
void* value = RawCurrentThreadGet();
if (UNLIKELY(!value)) {
value = reinterpret_cast<void*>(internal::CurrentThreadSyscall());
DCHECK(value);
RawCurrentThreadSet(value);
}
return reinterpret_cast<ThreadIdentifier>(value);
}
// For debugging only -- whether a non-main thread has been created.
// No synchronization is required, since this is called before any such thread
// exists.
#if DCHECK_IS_ON()
static bool g_thread_created = false;
bool IsBeforeThreadCreated() {
return !g_thread_created;
}
void WillCreateThread() {
g_thread_created = true;
}
#endif
} // namespace WTF
...@@ -62,67 +62,6 @@ ...@@ -62,67 +62,6 @@
namespace WTF { namespace WTF {
namespace internal {
ThreadIdentifier CurrentThreadSyscall() {
#if defined(OS_MACOSX)
return pthread_mach_thread_np(pthread_self());
#elif defined(OS_LINUX)
return syscall(__NR_gettid);
#elif defined(OS_ANDROID)
return gettid();
#else
return reinterpret_cast<uintptr_t>(pthread_self());
#endif
}
} // namespace internal
void InitializeThreading() {
// This should only be called once.
WTFThreadData::Initialize();
InitializeDates();
// Force initialization of static DoubleToStringConverter converter variable
// inside EcmaScriptConverter function while we are in single thread mode.
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
}
namespace {
pthread_key_t g_current_thread_key;
bool g_current_thread_key_initialized = false;
} // namespace
void InitializeCurrentThread() {
DCHECK(!g_current_thread_key_initialized);
int error = pthread_key_create(&g_current_thread_key, nullptr);
CHECK(!error);
g_current_thread_key_initialized = true;
}
ThreadIdentifier CurrentThread() {
// This doesn't use WTF::ThreadSpecific (e.g. WTFThreadData) because
// ThreadSpecific now depends on currentThread. It is necessary to avoid this
// or a similar loop:
//
// currentThread
// -> wtfThreadData
// -> ThreadSpecific::operator*
// -> isMainThread
// -> currentThread
static_assert(sizeof(ThreadIdentifier) <= sizeof(void*),
"ThreadIdentifier must fit in a void*.");
DCHECK(g_current_thread_key_initialized);
void* value = pthread_getspecific(g_current_thread_key);
if (UNLIKELY(!value)) {
value = reinterpret_cast<void*>(
static_cast<intptr_t>(internal::CurrentThreadSyscall()));
DCHECK(value);
pthread_setspecific(g_current_thread_key, value);
}
return reinterpret_cast<intptr_t>(pthread_getspecific(g_current_thread_key));
}
MutexBase::MutexBase(bool recursive) { MutexBase::MutexBase(bool recursive) {
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
...@@ -252,25 +191,6 @@ void ThreadCondition::Broadcast() { ...@@ -252,25 +191,6 @@ void ThreadCondition::Broadcast() {
DCHECK_EQ(result, 0); DCHECK_EQ(result, 0);
} }
#if DCHECK_IS_ON()
static bool g_thread_created = false;
Mutex& GetThreadCreatedMutex() {
static Mutex g_thread_created_mutex;
return g_thread_created_mutex;
}
bool IsBeforeThreadCreated() {
MutexLocker locker(GetThreadCreatedMutex());
return !g_thread_created;
}
void WillCreateThread() {
MutexLocker locker(GetThreadCreatedMutex());
g_thread_created = true;
}
#endif
} // namespace WTF } // namespace WTF
#endif // defined(OS_POSIX) || defined(OS_FUCHSIA) #endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
...@@ -106,83 +106,11 @@ ...@@ -106,83 +106,11 @@
#include <process.h> #include <process.h>
#include <windows.h> #include <windows.h>
#include "base/threading/scoped_blocking_call.h" #include "base/threading/scoped_blocking_call.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" #include "third_party/blink/renderer/platform/wtf/threading_primitives.h"
#include "third_party/blink/renderer/platform/wtf/time.h" #include "third_party/blink/renderer/platform/wtf/time.h"
#include "third_party/blink/renderer/platform/wtf/wtf_thread_data.h"
namespace WTF { namespace WTF {
// THREADNAME_INFO comes from
// <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>.
#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO {
DWORD dw_type; // must be 0x1000
LPCSTR sz_name; // pointer to name (in user addr space)
DWORD dw_thread_id; // thread ID (-1=caller thread)
DWORD dw_flags; // reserved for future use, must be zero
} THREADNAME_INFO;
#pragma pack(pop)
namespace internal {
ThreadIdentifier CurrentThreadSyscall() {
return static_cast<ThreadIdentifier>(GetCurrentThreadId());
}
} // namespace internal
void InitializeThreading() {
// This should only be called once.
WTFThreadData::Initialize();
InitializeDates();
// Force initialization of static DoubleToStringConverter converter variable
// inside EcmaScriptConverter function while we are in single thread mode.
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
}
namespace {
DWORD g_current_thread_key;
bool g_current_thread_key_initialized = false;
} // namespace
void InitializeCurrentThread() {
DCHECK(!g_current_thread_key_initialized);
// This key is never destroyed.
g_current_thread_key = ::TlsAlloc();
CHECK_NE(g_current_thread_key, TLS_OUT_OF_INDEXES);
g_current_thread_key_initialized = true;
}
ThreadIdentifier CurrentThread() {
// This doesn't use WTF::ThreadSpecific (e.g. WTFThreadData) because
// ThreadSpecific now depends on currentThread. It is necessary to avoid this
// or a similar loop:
//
// currentThread
// -> wtfThreadData
// -> ThreadSpecific::operator*
// -> isMainThread
// -> currentThread
static_assert(sizeof(ThreadIdentifier) <= sizeof(void*),
"ThreadIdentifier must fit in a void*.");
DCHECK(g_current_thread_key_initialized);
void* value = ::TlsGetValue(g_current_thread_key);
if (UNLIKELY(!value)) {
value = reinterpret_cast<void*>(internal::CurrentThreadSyscall());
DCHECK(value);
::TlsSetValue(g_current_thread_key, value);
}
return reinterpret_cast<intptr_t>(::TlsGetValue(g_current_thread_key));
}
MutexBase::MutexBase(bool recursive) { MutexBase::MutexBase(bool recursive) {
mutex_.recursion_count_ = 0; mutex_.recursion_count_ = 0;
InitializeCriticalSection(&mutex_.internal_mutex_); InitializeCriticalSection(&mutex_.internal_mutex_);
...@@ -290,25 +218,6 @@ void ThreadCondition::Broadcast() { ...@@ -290,25 +218,6 @@ void ThreadCondition::Broadcast() {
WakeAllConditionVariable(&condition_); WakeAllConditionVariable(&condition_);
} }
#if DCHECK_IS_ON()
static bool g_thread_created = false;
Mutex& GetThreadCreatedMutex() {
static Mutex g_thread_created_mutex;
return g_thread_created_mutex;
}
bool IsBeforeThreadCreated() {
MutexLocker locker(GetThreadCreatedMutex());
return !g_thread_created;
}
void WillCreateThread() {
MutexLocker locker(GetThreadCreatedMutex());
g_thread_created = true;
}
#endif
} // namespace WTF } // namespace WTF
#endif // defined(OS_WIN) #endif // defined(OS_WIN)
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "third_party/blink/renderer/platform/wtf/allocator/partitions.h" #include "third_party/blink/renderer/platform/wtf/allocator/partitions.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/date_math.h"
#include "third_party/blink/renderer/platform/wtf/dtoa/double-conversion.h"
#include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/stack_util.h" #include "third_party/blink/renderer/platform/wtf/stack_util.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
...@@ -39,11 +41,10 @@ ...@@ -39,11 +41,10 @@
#include "third_party/blink/renderer/platform/wtf/thread_specific.h" #include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/threading.h" #include "third_party/blink/renderer/platform/wtf/threading.h"
#include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h" #include "third_party/blink/renderer/platform/wtf/typed_arrays/array_buffer_contents.h"
#include "third_party/blink/renderer/platform/wtf/wtf_thread_data.h"
namespace WTF { namespace WTF {
extern void InitializeThreading();
bool g_initialized; bool g_initialized;
void (*g_call_on_main_thread_function)(MainThreadFunction, void*); void (*g_call_on_main_thread_function)(MainThreadFunction, void*);
ThreadIdentifier g_main_thread_identifier; ThreadIdentifier g_main_thread_identifier;
...@@ -69,7 +70,13 @@ void Initialize(void (*call_on_main_thread_function)(MainThreadFunction, ...@@ -69,7 +70,13 @@ void Initialize(void (*call_on_main_thread_function)(MainThreadFunction,
InitializeCurrentThread(); InitializeCurrentThread();
g_main_thread_identifier = CurrentThread(); g_main_thread_identifier = CurrentThread();
InitializeThreading(); WTFThreadData::Initialize();
InitializeDates();
// Force initialization of static DoubleToStringConverter converter variable
// inside EcmaScriptConverter function while we are in single thread mode.
double_conversion::DoubleToStringConverter::EcmaScriptConverter();
g_call_on_main_thread_function = call_on_main_thread_function; g_call_on_main_thread_function = call_on_main_thread_function;
internal::InitializeMainThreadStackEstimate(); internal::InitializeMainThreadStackEstimate();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment