diff options
Diffstat (limited to 'js/src/threading/windows/WindowsThread.cpp')
-rw-r--r-- | js/src/threading/windows/WindowsThread.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/js/src/threading/windows/WindowsThread.cpp b/js/src/threading/windows/WindowsThread.cpp new file mode 100644 index 0000000000..68d4808ebd --- /dev/null +++ b/js/src/threading/windows/WindowsThread.cpp @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <chrono> +#include <thread> + +#include "threading/Thread.h" +#include "threading/windows/ThreadPlatformData.h" + +namespace js { + +inline ThreadId::PlatformData* ThreadId::platformData() { + static_assert(sizeof platformData_ >= sizeof(PlatformData), + "platformData_ is too small"); + return reinterpret_cast<PlatformData*>(platformData_); +} + +inline const ThreadId::PlatformData* ThreadId::platformData() const { + static_assert(sizeof platformData_ >= sizeof(PlatformData), + "platformData_ is too small"); + return reinterpret_cast<const PlatformData*>(platformData_); +} + +ThreadId::ThreadId() { + platformData()->handle = nullptr; + platformData()->id = 0; +} + +ThreadId::operator bool() const { return platformData()->handle; } + +bool ThreadId::operator==(const ThreadId& aOther) const { + return platformData()->id == aOther.platformData()->id; +} + +bool Thread::create(unsigned int(__stdcall* aMain)(void*), void* aArg) { + MOZ_RELEASE_ASSERT(!joinable()); + + if (oom::ShouldFailWithOOM()) { + return false; + } + + // Use _beginthreadex and not CreateThread, because threads that are + // created with the latter leak a small amount of memory when they use + // certain msvcrt functions and then exit. + uintptr_t handle = _beginthreadex(nullptr, options_.stackSize(), aMain, aArg, + STACK_SIZE_PARAM_IS_A_RESERVATION, + &id_.platformData()->id); + if (!handle) { + // On either Windows or POSIX we can't be sure if id_ was initalisad. So + // reset it manually. + id_ = ThreadId(); + return false; + } + id_.platformData()->handle = reinterpret_cast<HANDLE>(handle); + return true; +} + +void Thread::join() { + MOZ_RELEASE_ASSERT(joinable()); + DWORD r = WaitForSingleObject(id_.platformData()->handle, INFINITE); + MOZ_RELEASE_ASSERT(r == WAIT_OBJECT_0); + BOOL success = CloseHandle(id_.platformData()->handle); + MOZ_RELEASE_ASSERT(success); + id_ = ThreadId(); +} + +void Thread::detach() { + MOZ_RELEASE_ASSERT(joinable()); + BOOL success = CloseHandle(id_.platformData()->handle); + MOZ_RELEASE_ASSERT(success); + id_ = ThreadId(); +} + +ThreadId ThreadId::ThisThreadId() { + ThreadId id; + id.platformData()->handle = GetCurrentThread(); + id.platformData()->id = GetCurrentThreadId(); + MOZ_RELEASE_ASSERT(id != ThreadId()); + return id; +} + +void ThisThread::SetName(const char* name) { + MOZ_RELEASE_ASSERT(name); + +#ifdef _MSC_VER + // Setting the thread name requires compiler support for structured + // exceptions, so this only works when compiled with MSVC. + static const DWORD THREAD_NAME_EXCEPTION = 0x406D1388; + static const DWORD THREAD_NAME_INFO_TYPE = 0x1000; + +# pragma pack(push, 8) + struct THREADNAME_INFO { + DWORD dwType; + LPCSTR szName; + DWORD dwThreadID; + DWORD dwFlags; + }; +# pragma pack(pop) + + THREADNAME_INFO info; + info.dwType = THREAD_NAME_INFO_TYPE; + info.szName = name; + info.dwThreadID = GetCurrentThreadId(); + info.dwFlags = 0; + + __try { + RaiseException(THREAD_NAME_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), + (ULONG_PTR*)&info); + } __except (EXCEPTION_EXECUTE_HANDLER) { + // Do nothing. + } +#endif // _MSC_VER +} + +void ThisThread::GetName(char* nameBuffer, size_t len) { + MOZ_RELEASE_ASSERT(len > 0); + *nameBuffer = '\0'; +} + +void ThisThread::SleepMilliseconds(size_t ms) { + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +} + +} // namespace js |