summaryrefslogtreecommitdiffstats
path: root/js/src/threading/windows/WindowsThread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/threading/windows/WindowsThread.cpp')
-rw-r--r--js/src/threading/windows/WindowsThread.cpp127
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