tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

WindowsThread.cpp (3776B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <chrono>
      8 #include <thread>
      9 
     10 #include "threading/Thread.h"
     11 #include "threading/windows/ThreadPlatformData.h"
     12 
     13 namespace js {
     14 
     15 inline ThreadId::PlatformData* ThreadId::platformData() {
     16  static_assert(sizeof platformData_ >= sizeof(PlatformData),
     17                "platformData_ is too small");
     18  return reinterpret_cast<PlatformData*>(platformData_);
     19 }
     20 
     21 inline const ThreadId::PlatformData* ThreadId::platformData() const {
     22  static_assert(sizeof platformData_ >= sizeof(PlatformData),
     23                "platformData_ is too small");
     24  return reinterpret_cast<const PlatformData*>(platformData_);
     25 }
     26 
     27 ThreadId::ThreadId() {
     28  platformData()->handle = nullptr;
     29  platformData()->id = 0;
     30 }
     31 
     32 ThreadId::operator bool() const { return platformData()->handle; }
     33 
     34 bool ThreadId::operator==(const ThreadId& aOther) const {
     35  return platformData()->id == aOther.platformData()->id;
     36 }
     37 
     38 bool Thread::create(unsigned int(__stdcall* aMain)(void*), void* aArg) {
     39  MOZ_RELEASE_ASSERT(!joinable());
     40 
     41  if (oom::ShouldFailWithOOM()) {
     42    return false;
     43  }
     44 
     45  // Use _beginthreadex and not CreateThread, because threads that are
     46  // created with the latter leak a small amount of memory when they use
     47  // certain msvcrt functions and then exit.
     48  uintptr_t handle = _beginthreadex(nullptr, options_.stackSize(), aMain, aArg,
     49                                    STACK_SIZE_PARAM_IS_A_RESERVATION,
     50                                    &id_.platformData()->id);
     51  if (!handle) {
     52    // On either Windows or POSIX we can't be sure if id_ was initalisad. So
     53    // reset it manually.
     54    id_ = ThreadId();
     55    return false;
     56  }
     57  id_.platformData()->handle = reinterpret_cast<HANDLE>(handle);
     58  return true;
     59 }
     60 
     61 void Thread::join() {
     62  MOZ_RELEASE_ASSERT(joinable());
     63  DWORD r = WaitForSingleObject(id_.platformData()->handle, INFINITE);
     64  MOZ_RELEASE_ASSERT(r == WAIT_OBJECT_0);
     65  BOOL success = CloseHandle(id_.platformData()->handle);
     66  MOZ_RELEASE_ASSERT(success);
     67  id_ = ThreadId();
     68 }
     69 
     70 void Thread::detach() {
     71  MOZ_RELEASE_ASSERT(joinable());
     72  BOOL success = CloseHandle(id_.platformData()->handle);
     73  MOZ_RELEASE_ASSERT(success);
     74  id_ = ThreadId();
     75 }
     76 
     77 ThreadId ThreadId::ThisThreadId() {
     78  ThreadId id;
     79  id.platformData()->handle = GetCurrentThread();
     80  id.platformData()->id = GetCurrentThreadId();
     81  MOZ_RELEASE_ASSERT(id != ThreadId());
     82  return id;
     83 }
     84 
     85 void ThisThread::SetName(const char* name) {
     86  MOZ_RELEASE_ASSERT(name);
     87 
     88 #ifdef _MSC_VER
     89  // Setting the thread name requires compiler support for structured
     90  // exceptions, so this only works when compiled with MSVC.
     91  static const DWORD THREAD_NAME_EXCEPTION = 0x406D1388;
     92  static const DWORD THREAD_NAME_INFO_TYPE = 0x1000;
     93 
     94 #  pragma pack(push, 8)
     95  struct THREADNAME_INFO {
     96    DWORD dwType;
     97    LPCSTR szName;
     98    DWORD dwThreadID;
     99    DWORD dwFlags;
    100  };
    101 #  pragma pack(pop)
    102 
    103  THREADNAME_INFO info;
    104  info.dwType = THREAD_NAME_INFO_TYPE;
    105  info.szName = name;
    106  info.dwThreadID = GetCurrentThreadId();
    107  info.dwFlags = 0;
    108 
    109  __try {
    110    RaiseException(THREAD_NAME_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
    111                   (ULONG_PTR*)&info);
    112  } __except (EXCEPTION_EXECUTE_HANDLER) {
    113    // Do nothing.
    114  }
    115 #endif  // _MSC_VER
    116 }
    117 
    118 void ThisThread::GetName(char* nameBuffer, size_t len) {
    119  MOZ_RELEASE_ASSERT(len > 0);
    120  *nameBuffer = '\0';
    121 }
    122 
    123 void ThisThread::SleepMilliseconds(size_t ms) {
    124  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
    125 }
    126 
    127 }  // namespace js