tor-browser

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

PosixThread.cpp (4214B)


      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 "mozilla/Assertions.h"
      8 
      9 #include <chrono>
     10 #include <thread>
     11 
     12 #include "js/Utility.h"
     13 #include "threading/posix/ThreadPlatformData.h"
     14 #include "threading/Thread.h"
     15 
     16 namespace js {
     17 
     18 inline ThreadId::PlatformData* ThreadId::platformData() {
     19  static_assert(sizeof platformData_ >= sizeof(PlatformData),
     20                "platformData_ is too small");
     21  return reinterpret_cast<PlatformData*>(platformData_);
     22 }
     23 
     24 inline const ThreadId::PlatformData* ThreadId::platformData() const {
     25  static_assert(sizeof platformData_ >= sizeof(PlatformData),
     26                "platformData_ is too small");
     27  return reinterpret_cast<const PlatformData*>(platformData_);
     28 }
     29 
     30 ThreadId::ThreadId() { platformData()->hasThread = false; }
     31 
     32 ThreadId::operator bool() const { return platformData()->hasThread; }
     33 
     34 bool ThreadId::operator==(const ThreadId& aOther) const {
     35  const PlatformData& self = *platformData();
     36  const PlatformData& other = *aOther.platformData();
     37  return (!self.hasThread && !other.hasThread) ||
     38         (self.hasThread == other.hasThread &&
     39          pthread_equal(self.ptThread, other.ptThread));
     40 }
     41 
     42 bool Thread::create(void* (*aMain)(void*), void* aArg) {
     43  MOZ_RELEASE_ASSERT(!joinable());
     44 
     45  if (oom::ShouldFailWithOOM()) {
     46    return false;
     47  }
     48 
     49  pthread_attr_t attrs;
     50  int r = pthread_attr_init(&attrs);
     51  MOZ_RELEASE_ASSERT(!r);
     52  if (options_.stackSize()) {
     53    r = pthread_attr_setstacksize(&attrs, options_.stackSize());
     54    MOZ_RELEASE_ASSERT(!r);
     55  }
     56 
     57  r = pthread_create(&id_.platformData()->ptThread, &attrs, aMain, aArg);
     58  if (r) {
     59    // On either Windows or POSIX we can't be sure if id_ was initialised. So
     60    // reset it manually.
     61    id_ = ThreadId();
     62    return false;
     63  }
     64  id_.platformData()->hasThread = true;
     65  return true;
     66 }
     67 
     68 void Thread::join() {
     69  MOZ_RELEASE_ASSERT(joinable());
     70  int r = pthread_join(id_.platformData()->ptThread, nullptr);
     71  MOZ_RELEASE_ASSERT(!r);
     72  id_ = ThreadId();
     73 }
     74 
     75 void Thread::detach() {
     76  MOZ_RELEASE_ASSERT(joinable());
     77  int r = pthread_detach(id_.platformData()->ptThread);
     78  MOZ_RELEASE_ASSERT(!r);
     79  id_ = ThreadId();
     80 }
     81 
     82 ThreadId ThreadId::ThisThreadId() {
     83  ThreadId id;
     84  id.platformData()->ptThread = pthread_self();
     85  id.platformData()->hasThread = true;
     86  MOZ_RELEASE_ASSERT(id != ThreadId());
     87  return id;
     88 }
     89 
     90 void ThisThread::SetName(const char* name) {
     91  MOZ_RELEASE_ASSERT(name);
     92 
     93 #if (defined(__APPLE__) && defined(__MACH__)) || defined(__linux__)
     94 #  if defined(XP_DARWIN)
     95  // Mac OS X has a length limit of 63 characters, but there is no API
     96  // exposing it.
     97 #    define SETNAME_LENGTH_CONSTRAINT 63
     98 #  else
     99  // On linux the name may not be longer than 16 bytes, including
    100  // the null terminator. Truncate the name to 15 characters.
    101 #    define SETNAME_LENGTH_CONSTRAINT 15
    102 #  endif
    103  char nameBuf[SETNAME_LENGTH_CONSTRAINT + 1];
    104 
    105  strncpy(nameBuf, name, sizeof nameBuf - 1);
    106  nameBuf[sizeof nameBuf - 1] = '\0';
    107  name = nameBuf;
    108 #endif
    109 
    110  int rv;
    111 #ifdef XP_DARWIN
    112  rv = pthread_setname_np(name);
    113 #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
    114  pthread_set_name_np(pthread_self(), name);
    115  rv = 0;
    116 #elif defined(__NetBSD__)
    117  rv = pthread_setname_np(pthread_self(), "%s", (void*)name);
    118 #else
    119  rv = pthread_setname_np(pthread_self(), name);
    120 #endif
    121  MOZ_RELEASE_ASSERT(!rv);
    122 }
    123 
    124 void ThisThread::GetName(char* nameBuffer, size_t len) {
    125  MOZ_RELEASE_ASSERT(len >= 16);
    126 
    127  int rv = -1;
    128 #ifdef HAVE_PTHREAD_GETNAME_NP
    129  rv = pthread_getname_np(pthread_self(), nameBuffer, len);
    130 #elif defined(HAVE_PTHREAD_GET_NAME_NP)
    131  pthread_get_name_np(pthread_self(), nameBuffer, len);
    132  rv = 0;
    133 #elif defined(__linux__)
    134  rv = prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(nameBuffer));
    135 #endif
    136 
    137  if (rv) {
    138    nameBuffer[0] = '\0';
    139  }
    140 }
    141 
    142 void ThisThread::SleepMilliseconds(size_t ms) {
    143  std::this_thread::sleep_for(std::chrono::milliseconds(ms));
    144 }
    145 
    146 }  // namespace js