6#if defined(DART_HOST_OS_WINDOWS) && !defined(DART_USE_ABSL)
23 worker_thread_priority,
25 "The thread priority the VM should use for new worker threads.");
29bool private_flag_windows_run_tls_destructors =
true;
31class ThreadStartData {
33 ThreadStartData(
const char*
name,
36 : name_(
name), function_(
function), parameter_(parameter) {}
38 const char*
name()
const {
return name_; }
40 uword parameter()
const {
return parameter_; }
53static unsigned int __stdcall ThreadEntry(
void* data_ptr) {
54 if (FLAG_worker_thread_priority !=
kMinInt) {
55 if (SetThreadPriority(GetCurrentThread(), FLAG_worker_thread_priority) ==
57 FATAL(
"Setting thread priority to %d failed: GetLastError() = %d\n",
62 ThreadStartData*
data =
reinterpret_cast<ThreadStartData*
>(data_ptr);
71 if (thread !=
nullptr) {
73 thread->SetName(
name);
85 ThreadStartData* start_data =
new ThreadStartData(
name,
function, parameter);
88 ThreadEntry, start_data, 0, &tid);
89 if (thread == -1L || thread == 0) {
91 fprintf(stderr,
"_beginthreadex error: %d (%s)\n", errno, strerror(errno));
97 CloseHandle(
reinterpret_cast<HANDLE>(thread));
110 ThreadLocalData::AddThreadLocal(
key, destructor);
120 ThreadLocalData::RemoveThreadLocal(
key);
129 return ::GetCurrentThreadId();
132#ifdef SUPPORT_TIMELINE
133ThreadId OSThread::GetCurrentThreadTraceId() {
134 return ::GetCurrentThreadId();
138char* OSThread::GetCurrentThreadName() {
145 ASSERT(thread !=
nullptr);
148 ASSERT(thread->id() ==
id);
152 ASSERT(handle !=
nullptr);
154 thread->join_id_ = handle;
161 ASSERT(handle !=
nullptr);
162 DWORD res = WaitForSingleObject(handle, INFINITE);
164 ASSERT(res == WAIT_OBJECT_0);
169 return static_cast<intptr_t
>(
id);
183 NT_TIB* tib =
reinterpret_cast<NT_TIB*
>(NtCurrentTeb());
184 *upper =
reinterpret_cast<uword>(tib->StackBase);
188 MEMORY_BASIC_INFORMATION stack_info;
189 memset(&stack_info, 0,
sizeof(MEMORY_BASIC_INFORMATION));
191 VirtualQuery(&stack_info, &stack_info,
sizeof(MEMORY_BASIC_INFORMATION));
192 ASSERT(result_size >=
sizeof(MEMORY_BASIC_INFORMATION));
193 *
lower =
reinterpret_cast<uword>(stack_info.AllocationBase);
203 *
lower += 4 * 0x1000;
207#if defined(USING_SAFE_STACK)
210uword OSThread::GetCurrentSafestackPointer() {
211#error "SAFE_STACK is unsupported on this platform"
217void OSThread::SetCurrentSafestackPointer(
uword ssp) {
218#error "SAFE_STACK is unsupported on this platform"
235 InitializeSRWLock(&data_.lock_);
250 DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
252 AcquireSRWLockExclusive(&data_.lock_);
259bool Mutex::TryLock() {
260 DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
272void Mutex::Unlock() {
282 InitializeSRWLock(&data_.lock_);
283 InitializeConditionVariable(&data_.cond_);
297bool Monitor::TryEnter() {
298 DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
312void Monitor::Enter() {
313 DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
315 AcquireSRWLockExclusive(&data_.lock_);
324void Monitor::Exit() {
344 SleepConditionVariableSRW(&data_.cond_, &data_.lock_, INFINITE, 0);
348 if (!SleepConditionVariableSRW(&data_.cond_, &data_.lock_, millis, 0)) {
358 ASSERT(owner_ == saved_owner);
375void Monitor::Notify() {
378 WakeConditionVariable(&data_.cond_);
381void Monitor::NotifyAll() {
384 WakeAllConditionVariable(&data_.cond_);
389 ASSERT(thread_locals_ !=
nullptr);
390 if (destructor ==
nullptr) {
394 MutexLocker ml(mutex_);
397 for (intptr_t
i = 0;
i < thread_locals_->length();
i++) {
398 const ThreadLocalEntry& entry = thread_locals_->At(
i);
403 thread_locals_->Add(ThreadLocalEntry(
key, destructor));
407 ASSERT(thread_locals_ !=
nullptr);
408 MutexLocker ml(mutex_);
410 for (;
i < thread_locals_->length();
i++) {
411 const ThreadLocalEntry& entry = thread_locals_->At(
i);
412 if (entry.key() ==
key) {
416 if (
i == thread_locals_->length()) {
420 thread_locals_->RemoveAt(
i);
429 if (thread_locals_ ==
nullptr) {
432 ASSERT(mutex_ !=
nullptr);
433 MutexLocker ml(mutex_);
434 for (intptr_t
i = 0;
i < thread_locals_->length();
i++) {
435 const ThreadLocalEntry& entry = thread_locals_->At(
i);
439 entry.destructor()(
p);
443Mutex* ThreadLocalData::mutex_ =
nullptr;
444MallocGrowableArray<ThreadLocalEntry>* ThreadLocalData::thread_locals_ =
447void ThreadLocalData::Init() {
448 mutex_ =
new Mutex();
449 thread_locals_ =
new MallocGrowableArray<ThreadLocalEntry>();
452void ThreadLocalData::Cleanup() {
453 if (mutex_ !=
nullptr) {
457 if (thread_locals_ !=
nullptr) {
458 delete thread_locals_;
459 thread_locals_ =
nullptr;
481#pragma comment(linker, "/INCLUDE:_tls_used")
482#pragma comment(linker, "/INCLUDE:p_thread_callback_dart")
486#pragma comment(linker, "/INCLUDE:__tls_used")
487#pragma comment(linker, "/INCLUDE:_p_thread_callback_dart")
492void NTAPI OnDartThreadExit(
PVOID module,
DWORD reason,
PVOID reserved) {
493 if (!dart::private_flag_windows_run_tls_destructors) {
498 if (DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) {
524#pragma const_seg(".CRT$XLB")
527extern const PIMAGE_TLS_CALLBACK p_thread_callback_dart;
528const PIMAGE_TLS_CALLBACK p_thread_callback_dart = OnDartThreadExit;
535#pragma data_seg(".CRT$XLB")
536PIMAGE_TLS_CALLBACK p_thread_callback_dart = OnDartThreadExit;
#define NO_SANITIZE_ADDRESS
#define DEBUG_ASSERT(cond)
bool IsOwnedByCurrentThread() const
static constexpr int64_t kNoTimeout
Mutex(NOT_IN_PRODUCT(const char *name="anonymous mutex"))
bool IsOwnedByCurrentThread() const
static void DeleteThreadLocal(ThreadLocalKey key)
static int Start(const char *name, ThreadStartFunction function, uword parameter)
const char * name() const
static bool GetCurrentStackBounds(uword *lower, uword *upper)
static OSThread * CreateOSThread()
static void SetCurrent(OSThread *current)
static uword GetThreadLocal(ThreadLocalKey key)
static ThreadId ThreadIdFromIntPtr(intptr_t id)
static ThreadId GetCurrentThreadId()
static void Join(ThreadJoinId id)
static bool Compare(ThreadId a, ThreadId b)
static ThreadLocalKey CreateThreadLocal(ThreadDestructor destructor=nullptr)
static const ThreadId kInvalidThreadId
static ThreadJoinId GetCurrentThreadJoinId(OSThread *thread)
void(* ThreadStartFunction)(uword parameter)
static void SetThreadLocal(ThreadLocalKey key, uword value)
static intptr_t ThreadIdToIntPtr(ThreadId id)
static intptr_t GetMaxStackSize()
static const ThreadJoinId kInvalidThreadJoinId
static void RunDestructors()
Dart_NativeFunction function
constexpr intptr_t kMicrosecondsPerMillisecond
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")
void(* ThreadDestructor)(void *parameter)
constexpr intptr_t kWordSize
pthread_key_t ThreadLocalKey
static int8_t data[kExtLength]
NOT_IN_PRODUCT(LibraryPtr ReloadTestScript(const char *script))
static const ThreadLocalKey kUnsetThreadLocalKey
COMPILE_ASSERT(kUnreachableReference==WeakTable::kNoValue)
#define NO_SANITIZE_SAFE_STACK
WINBASEAPI BOOLEAN WINAPI TryAcquireSRWLockExclusive(_Inout_ PSRWLOCK SRWLock)
WINBASEAPI _Releases_exclusive_lock_ SRWLock VOID WINAPI ReleaseSRWLockExclusive(_Inout_ PSRWLOCK SRWLock)
WINBASEAPI _Check_return_ _Post_equals_last_error_ DWORD WINAPI GetLastError(VOID)