LCOV - code coverage report
Current view: top level - js/src/threading/posix - Thread.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 41 70 58.6 %
Date: 2017-07-14 16:53:18 Functions: 8 13 61.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <new>
      10             : #include <pthread.h>
      11             : #include <stdlib.h>
      12             : #include <string.h>
      13             : 
      14             : #if defined(__APPLE__) && defined(__MACH__)
      15             : #include <dlfcn.h>
      16             : #endif
      17             : 
      18             : #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
      19             : #include <pthread_np.h>
      20             : #endif
      21             : 
      22             : #if defined(__linux__)
      23             : #include <sys/prctl.h>
      24             : #endif
      25             : 
      26             : #include "threading/Thread.h"
      27             : 
      28             : class js::Thread::Id::PlatformData
      29             : {
      30             :   friend class js::Thread;
      31             :   friend js::Thread::Id js::ThisThread::GetId();
      32             : 
      33             :   pthread_t ptThread;
      34             : 
      35             :   // pthread_t does not have a default initializer, so we have to carry a bool
      36             :   // to tell whether it is safe to compare or not.
      37             :   bool hasThread;
      38             : };
      39             : 
      40             : /* static */ js::HashNumber
      41           0 : js::Thread::Hasher::hash(const Lookup& l)
      42             : {
      43           0 :   return mozilla::HashBytes(&l.platformData()->ptThread, sizeof(pthread_t));
      44             : }
      45             : 
      46             : inline js::Thread::Id::PlatformData*
      47     5850580 : js::Thread::Id::platformData()
      48             : {
      49             :   static_assert(sizeof platformData_ >= sizeof(PlatformData),
      50             :                 "platformData_ is too small");
      51     5850580 :   return reinterpret_cast<PlatformData*>(platformData_);
      52             : }
      53             : 
      54             : inline const js::Thread::Id::PlatformData*
      55     3895148 : js::Thread::Id::platformData() const
      56             : {
      57             :   static_assert(sizeof platformData_ >= sizeof(PlatformData),
      58             :                 "platformData_ is too small");
      59     3895148 :   return reinterpret_cast<const PlatformData*>(platformData_);
      60             : }
      61             : 
      62     1950412 : js::Thread::Id::Id()
      63             : {
      64     1950412 :   platformData()->hasThread = false;
      65     1950409 : }
      66             : 
      67             : bool
      68     1947594 : js::Thread::Id::operator==(const Id& aOther) const
      69             : {
      70     1947594 :   const PlatformData& self = *platformData();
      71     1947594 :   const PlatformData& other = *aOther.platformData();
      72     5842458 :   return (!self.hasThread && !other.hasThread) ||
      73     3894926 :          (self.hasThread == other.hasThread &&
      74     3895035 :           pthread_equal(self.ptThread, other.ptThread));
      75             : }
      76             : 
      77          72 : js::Thread::Thread(Thread&& aOther)
      78             : {
      79          72 :   id_ = aOther.id_;
      80          72 :   aOther.id_ = Id();
      81          72 :   options_ = aOther.options_;
      82          72 : }
      83             : 
      84             : js::Thread&
      85           0 : js::Thread::operator=(Thread&& aOther)
      86             : {
      87           0 :   MOZ_RELEASE_ASSERT(!joinable());
      88           0 :   id_ = aOther.id_;
      89           0 :   aOther.id_ = Id();
      90           0 :   options_ = aOther.options_;
      91           0 :   return *this;
      92             : }
      93             : 
      94             : bool
      95          36 : js::Thread::create(void* (*aMain)(void*), void* aArg)
      96             : {
      97             :   pthread_attr_t attrs;
      98          36 :   int r = pthread_attr_init(&attrs);
      99          36 :   MOZ_RELEASE_ASSERT(!r);
     100          36 :   if (options_.stackSize()) {
     101          36 :     r = pthread_attr_setstacksize(&attrs, options_.stackSize());
     102          36 :     MOZ_RELEASE_ASSERT(!r);
     103             :   }
     104          36 :   r = pthread_create(&id_.platformData()->ptThread, &attrs, aMain, aArg);
     105          36 :   if (r) {
     106             :     // |pthread_create| may leave id_ in an undefined state.
     107           0 :     id_ = Id();
     108           0 :     return false;
     109             :   }
     110          36 :   id_.platformData()->hasThread = true;
     111          36 :   return true;
     112             : }
     113             : 
     114             : void
     115           0 : js::Thread::join()
     116             : {
     117           0 :   MOZ_RELEASE_ASSERT(joinable());
     118           0 :   int r = pthread_join(id_.platformData()->ptThread, nullptr);
     119           0 :   MOZ_RELEASE_ASSERT(!r);
     120           0 :   id_ = Id();
     121           0 : }
     122             : 
     123             : void
     124           0 : js::Thread::detach()
     125             : {
     126           0 :   MOZ_RELEASE_ASSERT(joinable());
     127           0 :   int r = pthread_detach(id_.platformData()->ptThread);
     128           0 :   MOZ_RELEASE_ASSERT(!r);
     129           0 :   id_ = Id();
     130           0 : }
     131             : 
     132             : js::Thread::Id
     133     1950123 : js::ThisThread::GetId()
     134             : {
     135     1950123 :   js::Thread::Id id;
     136     1950120 :   id.platformData()->ptThread = pthread_self();
     137     1950114 :   id.platformData()->hasThread = true;
     138     1950177 :   return id;
     139             : }
     140             : 
     141             : void
     142          35 : js::ThisThread::SetName(const char* name)
     143             : {
     144          35 :   MOZ_RELEASE_ASSERT(name);
     145             : 
     146             : #if (defined(__APPLE__) && defined(__MACH__)) || defined(__linux__)
     147             :   // On linux and OS X the name may not be longer than 16 bytes, including
     148             :   // the null terminator. Truncate the name to 15 characters.
     149             :   char nameBuf[16];
     150             : 
     151          35 :   strncpy(nameBuf, name, sizeof nameBuf - 1);
     152          35 :   nameBuf[sizeof nameBuf - 1] = '\0';
     153          35 :   name = nameBuf;
     154             : #endif
     155             : 
     156             :   int rv;
     157             : #ifdef XP_DARWIN
     158             :   rv = pthread_setname_np(name);
     159             : #elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
     160             :   pthread_set_name_np(pthread_self(), name);
     161             :   rv = 0;
     162             : #elif defined(__NetBSD__)
     163             :   rv = pthread_setname_np(pthread_self(), "%s", (void*)name);
     164             : #else
     165          35 :   rv = pthread_setname_np(pthread_self(), name);
     166             : #endif
     167          35 :   MOZ_RELEASE_ASSERT(!rv);
     168          35 : }
     169             : 
     170             : void
     171           0 : js::ThisThread::GetName(char* nameBuffer, size_t len)
     172             : {
     173           0 :   MOZ_RELEASE_ASSERT(len >= 16);
     174             : 
     175           0 :   int rv = -1;
     176             : #ifdef HAVE_PTHREAD_GETNAME_NP
     177           0 :   rv = pthread_getname_np(pthread_self(), nameBuffer, len);
     178             : #elif defined(__linux__)
     179             :   rv = prctl(PR_GET_NAME, reinterpret_cast<unsigned long>(nameBuffer));
     180             : #endif
     181             : 
     182           0 :   if (rv)
     183           0 :     nameBuffer[0] = '\0';
     184           0 : }

Generated by: LCOV version 1.13