tor-browser

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

platform_thread_posix.cc (4348B)


      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 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 
      7 #include "base/platform_thread.h"
      8 
      9 #include <errno.h>
     10 #include <sched.h>
     11 
     12 #if defined(XP_DARWIN)
     13 #  include <mach/mach.h>
     14 #elif defined(XP_NETBSD)
     15 #  include <lwp.h>
     16 #elif defined(XP_LINUX)
     17 #  include <sys/syscall.h>
     18 #  include <sys/prctl.h>
     19 #endif
     20 
     21 #if !defined(XP_DARWIN)
     22 #  include <unistd.h>
     23 #endif
     24 
     25 #if (defined(__DragonFly__) || defined(XP_FREEBSD) || defined(XP_OPENBSD)) && \
     26    !defined(__GLIBC__)
     27 #  include <pthread_np.h>
     28 #endif
     29 
     30 #include "nsThreadUtils.h"
     31 
     32 #if defined(XP_DARWIN)
     33 namespace base {
     34 void InitThreading();
     35 }  // namespace base
     36 #endif
     37 
     38 static void* ThreadFunc(void* closure) {
     39  PlatformThread::Delegate* delegate =
     40      static_cast<PlatformThread::Delegate*>(closure);
     41  delegate->ThreadMain();
     42  return NULL;
     43 }
     44 
     45 // static
     46 PlatformThreadId PlatformThread::CurrentId() {
     47  // Pthreads doesn't have the concept of a thread ID, so we have to reach down
     48  // into the kernel.
     49 #if defined(XP_DARWIN)
     50  mach_port_t port = mach_thread_self();
     51  mach_port_deallocate(mach_task_self(), port);
     52  return port;
     53 #elif defined(XP_LINUX)
     54  return syscall(__NR_gettid);
     55 #elif defined(XP_OPENBSD) || defined(XP_SOLARIS) || defined(__GLIBC__)
     56  return (intptr_t)(pthread_self());
     57 #elif defined(XP_NETBSD)
     58  return _lwp_self();
     59 #elif defined(__DragonFly__)
     60  return lwp_gettid();
     61 #elif defined(XP_FREEBSD)
     62  return pthread_getthreadid_np();
     63 #endif
     64 }
     65 
     66 // static
     67 void PlatformThread::YieldCurrentThread() { sched_yield(); }
     68 
     69 // static
     70 void PlatformThread::Sleep(int duration_ms) {
     71  struct timespec sleep_time, remaining;
     72 
     73  // Contains the portion of duration_ms >= 1 sec.
     74  sleep_time.tv_sec = duration_ms / 1000;
     75  duration_ms -= sleep_time.tv_sec * 1000;
     76 
     77  // Contains the portion of duration_ms < 1 sec.
     78  sleep_time.tv_nsec = duration_ms * 1000 * 1000;  // nanoseconds.
     79 
     80  while (nanosleep(&sleep_time, &remaining) == -1 && errno == EINTR)
     81    sleep_time = remaining;
     82 }
     83 
     84 #ifndef XP_DARWIN
     85 // Mac is implemented in platform_thread_mac.mm.
     86 
     87 // static
     88 void PlatformThread::SetName(const char* name) {
     89  // On linux we can get the thread names to show up in the debugger by setting
     90  // the process name for the LWP.  We don't want to do this for the main
     91  // thread because that would rename the process, causing tools like killall
     92  // to stop working.
     93  if (PlatformThread::CurrentId() == getpid()) return;
     94 
     95  // Using NS_SetCurrentThreadName, as opposed to using platform APIs directly,
     96  // also sets the thread name on the PRThread wrapper, and allows us to
     97  // retrieve it using PR_GetThreadName.
     98  NS_SetCurrentThreadName(name);
     99 }
    100 #endif  // !XP_DARWIN
    101 
    102 namespace {
    103 
    104 bool CreateThread(size_t stack_size, bool joinable,
    105                  PlatformThread::Delegate* delegate,
    106                  PlatformThreadHandle* thread_handle) {
    107 #if defined(XP_DARWIN)
    108  base::InitThreading();
    109 #endif  // XP_DARWIN
    110 
    111  bool success = false;
    112  pthread_attr_t attributes;
    113  pthread_attr_init(&attributes);
    114 
    115  // Pthreads are joinable by default, so only specify the detached attribute if
    116  // the thread should be non-joinable.
    117  if (!joinable) {
    118    pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);
    119  }
    120 
    121  if (stack_size == 0) stack_size = nsIThreadManager::DEFAULT_STACK_SIZE;
    122  pthread_attr_setstacksize(&attributes, stack_size);
    123 
    124  success = !pthread_create(thread_handle, &attributes, ThreadFunc, delegate);
    125 
    126  pthread_attr_destroy(&attributes);
    127  return success;
    128 }
    129 
    130 }  // anonymous namespace
    131 
    132 // static
    133 bool PlatformThread::Create(size_t stack_size, Delegate* delegate,
    134                            PlatformThreadHandle* thread_handle) {
    135  return CreateThread(stack_size, true /* joinable thread */, delegate,
    136                      thread_handle);
    137 }
    138 
    139 // static
    140 bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
    141  PlatformThreadHandle unused;
    142 
    143  bool result = CreateThread(stack_size, false /* non-joinable thread */,
    144                             delegate, &unused);
    145  return result;
    146 }
    147 
    148 // static
    149 void PlatformThread::Join(PlatformThreadHandle thread_handle) {
    150  pthread_join(thread_handle, NULL);
    151 }