diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /js/src/threading/windows | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/threading/windows')
-rw-r--r-- | js/src/threading/windows/CpuCount.cpp | 20 | ||||
-rw-r--r-- | js/src/threading/windows/ThreadPlatformData.h | 30 | ||||
-rw-r--r-- | js/src/threading/windows/WindowsThread.cpp | 127 |
3 files changed, 177 insertions, 0 deletions
diff --git a/js/src/threading/windows/CpuCount.cpp b/js/src/threading/windows/CpuCount.cpp new file mode 100644 index 0000000000..39f8b49402 --- /dev/null +++ b/js/src/threading/windows/CpuCount.cpp @@ -0,0 +1,20 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "threading/CpuCount.h" + +#include "util/WindowsWrapper.h" + +uint32_t js::GetCPUCount() { + static uint32_t ncpus = 0; + + if (ncpus == 0) { + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + ncpus = uint32_t(sysinfo.dwNumberOfProcessors); + } + + return ncpus; +} diff --git a/js/src/threading/windows/ThreadPlatformData.h b/js/src/threading/windows/ThreadPlatformData.h new file mode 100644 index 0000000000..72baa80cc6 --- /dev/null +++ b/js/src/threading/windows/ThreadPlatformData.h @@ -0,0 +1,30 @@ +/* -*- 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/. */ + +#ifndef threading_windows_PlatformData_h +#define threading_windows_PlatformData_h + +#include <assert.h> +#include <new.h> +#include <process.h> + +#include "threading/Thread.h" + +#include "util/WindowsWrapper.h" + +namespace js { + +class ThreadId::PlatformData { + friend class Thread; + friend class ThreadId; + + HANDLE handle; + unsigned id; +}; + +} // namespace js + +#endif // threading_windows_PlatformData_h 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 |