LCOV - code coverage report
Current view: top level - src/base/platform - platform-posix.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 177 218 81.2 %
Date: 2019-01-20 Functions: 47 58 81.0 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : // Platform-specific code for POSIX goes here. This is not a platform on its
       6             : // own, but contains the parts which are the same across the POSIX platforms
       7             : // Linux, MacOS, FreeBSD, OpenBSD, NetBSD and QNX.
       8             : 
       9             : #include <errno.h>
      10             : #include <limits.h>
      11             : #include <pthread.h>
      12             : #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
      13             : #include <pthread_np.h>  // for pthread_set_name_np
      14             : #endif
      15             : #include <sched.h>  // for sched_yield
      16             : #include <stdio.h>
      17             : #include <time.h>
      18             : #include <unistd.h>
      19             : 
      20             : #include <sys/mman.h>
      21             : #include <sys/stat.h>
      22             : #include <sys/time.h>
      23             : #include <sys/types.h>
      24             : #if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
      25             :     defined(__NetBSD__) || defined(__OpenBSD__)
      26             : #include <sys/sysctl.h>  // NOLINT, for sysctl
      27             : #endif
      28             : 
      29             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
      30             : #define LOG_TAG "v8"
      31             : #include <android/log.h>  // NOLINT
      32             : #endif
      33             : 
      34             : #include <cmath>
      35             : #include <cstdlib>
      36             : 
      37             : #include "src/base/platform/platform-posix.h"
      38             : 
      39             : #include "src/base/lazy-instance.h"
      40             : #include "src/base/macros.h"
      41             : #include "src/base/platform/platform.h"
      42             : #include "src/base/platform/time.h"
      43             : #include "src/base/utils/random-number-generator.h"
      44             : 
      45             : #ifdef V8_FAST_TLS_SUPPORTED
      46             : #include "src/base/atomicops.h"
      47             : #endif
      48             : 
      49             : #if V8_OS_MACOSX
      50             : #include <dlfcn.h>
      51             : #endif
      52             : 
      53             : #if V8_OS_LINUX
      54             : #include <sys/prctl.h>  // NOLINT, for prctl
      55             : #endif
      56             : 
      57             : #if defined(V8_OS_FUCHSIA)
      58             : #include <zircon/process.h>
      59             : #else
      60             : #include <sys/resource.h>
      61             : #endif
      62             : 
      63             : #if !defined(_AIX) && !defined(V8_OS_FUCHSIA)
      64             : #include <sys/syscall.h>
      65             : #endif
      66             : 
      67             : #if V8_OS_FREEBSD || V8_OS_MACOSX || V8_OS_OPENBSD || V8_OS_SOLARIS
      68             : #define MAP_ANONYMOUS MAP_ANON
      69             : #endif
      70             : 
      71             : #if defined(V8_OS_SOLARIS)
      72             : #if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE > 2) || defined(__EXTENSIONS__)
      73             : extern "C" int madvise(caddr_t, size_t, int);
      74             : #else
      75             : extern int madvise(caddr_t, size_t, int);
      76             : #endif
      77             : #endif
      78             : 
      79             : #ifndef MADV_FREE
      80             : #define MADV_FREE MADV_DONTNEED
      81             : #endif
      82             : 
      83             : namespace v8 {
      84             : namespace base {
      85             : 
      86             : namespace {
      87             : 
      88             : // 0 is never a valid thread id.
      89             : const pthread_t kNoThread = static_cast<pthread_t>(0);
      90             : 
      91             : bool g_hard_abort = false;
      92             : 
      93             : const char* g_gc_fake_mmap = nullptr;
      94             : 
      95     2659252 : DEFINE_LAZY_LEAKY_OBJECT_GETTER(RandomNumberGenerator,
      96             :                                 GetPlatformRandomNumberGenerator);
      97             : static LazyMutex rng_mutex = LAZY_MUTEX_INITIALIZER;
      98             : 
      99             : #if !V8_OS_FUCHSIA
     100             : #if V8_OS_MACOSX
     101             : // kMmapFd is used to pass vm_alloc flags to tag the region with the user
     102             : // defined tag 255 This helps identify V8-allocated regions in memory analysis
     103             : // tools like vmmap(1).
     104             : const int kMmapFd = VM_MAKE_TAG(255);
     105             : #else   // !V8_OS_MACOSX
     106             : const int kMmapFd = -1;
     107             : #endif  // !V8_OS_MACOSX
     108             : 
     109             : const int kMmapFdOffset = 0;
     110             : 
     111    13861402 : int GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
     112    13861402 :   switch (access) {
     113             :     case OS::MemoryPermission::kNoAccess:
     114             :       return PROT_NONE;
     115             :     case OS::MemoryPermission::kRead:
     116       63325 :       return PROT_READ;
     117             :     case OS::MemoryPermission::kReadWrite:
     118     4934902 :       return PROT_READ | PROT_WRITE;
     119             :     case OS::MemoryPermission::kReadWriteExecute:
     120     1547851 :       return PROT_READ | PROT_WRITE | PROT_EXEC;
     121             :     case OS::MemoryPermission::kReadExecute:
     122     4007420 :       return PROT_READ | PROT_EXEC;
     123             :   }
     124           0 :   UNREACHABLE();
     125             : }
     126             : 
     127             : int GetFlagsForMemoryPermission(OS::MemoryPermission access) {
     128             :   int flags = MAP_PRIVATE | MAP_ANONYMOUS;
     129     2429353 :   if (access == OS::MemoryPermission::kNoAccess) {
     130             : #if !V8_OS_AIX && !V8_OS_FREEBSD && !V8_OS_QNX
     131             :     flags |= MAP_NORESERVE;
     132             : #endif  // !V8_OS_AIX && !V8_OS_FREEBSD && !V8_OS_QNX
     133             : #if V8_OS_QNX
     134             :     flags |= MAP_LAZY;
     135             : #endif  // V8_OS_QNX
     136             :   }
     137             :   return flags;
     138             : }
     139             : 
     140     2429357 : void* Allocate(void* address, size_t size, OS::MemoryPermission access) {
     141     2429357 :   int prot = GetProtectionFromMemoryPermission(access);
     142             :   int flags = GetFlagsForMemoryPermission(access);
     143     2429353 :   void* result = mmap(address, size, prot, flags, kMmapFd, kMmapFdOffset);
     144     2429378 :   if (result == MAP_FAILED) return nullptr;
     145     2429358 :   return result;
     146             : }
     147             : 
     148             : #endif  // !V8_OS_FUCHSIA
     149             : 
     150             : }  // namespace
     151             : 
     152       61281 : void OS::Initialize(bool hard_abort, const char* const gc_fake_mmap) {
     153       61281 :   g_hard_abort = hard_abort;
     154       61281 :   g_gc_fake_mmap = gc_fake_mmap;
     155       61281 : }
     156             : 
     157     1062920 : int OS::ActivationFrameAlignment() {
     158             : #if V8_TARGET_ARCH_ARM
     159             :   // On EABI ARM targets this is required for fp correctness in the
     160             :   // runtime system.
     161             :   return 8;
     162             : #elif V8_TARGET_ARCH_MIPS
     163             :   return 8;
     164             : #elif V8_TARGET_ARCH_S390
     165             :   return 8;
     166             : #else
     167             :   // Otherwise we just assume 16 byte alignment, i.e.:
     168             :   // - With gcc 4.4 the tree vectorization optimizer can generate code
     169             :   //   that requires 16 byte alignment such as movdqa on x86.
     170             :   // - Mac OS X, PPC and Solaris (64-bit) activation frames must
     171             :   //   be 16 byte-aligned;  see "Mac OS X ABI Function Call Guide"
     172     1062920 :   return 16;
     173             : #endif
     174             : }
     175             : 
     176             : // static
     177       61317 : size_t OS::AllocatePageSize() {
     178     5035489 :   return static_cast<size_t>(sysconf(_SC_PAGESIZE));
     179             : }
     180             : 
     181             : // static
     182       61317 : size_t OS::CommitPageSize() {
     183       61317 :   static size_t page_size = getpagesize();
     184       61317 :   return page_size;
     185             : }
     186             : 
     187             : // static
     188       59799 : void OS::SetRandomMmapSeed(int64_t seed) {
     189       59799 :   if (seed) {
     190             :     MutexGuard guard(rng_mutex.Pointer());
     191       59799 :     GetPlatformRandomNumberGenerator()->SetSeed(seed);
     192             :   }
     193       59799 : }
     194             : 
     195             : // static
     196     2538147 : void* OS::GetRandomMmapAddr() {
     197             :   uintptr_t raw_addr;
     198             :   {
     199             :     MutexGuard guard(rng_mutex.Pointer());
     200     2538174 :     GetPlatformRandomNumberGenerator()->NextBytes(&raw_addr, sizeof(raw_addr));
     201             :   }
     202             : #if defined(V8_USE_ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
     203             :     defined(THREAD_SANITIZER) || defined(LEAK_SANITIZER)
     204             :   // If random hint addresses interfere with address ranges hard coded in
     205             :   // sanitizers, bad things happen. This address range is copied from TSAN
     206             :   // source but works with all tools.
     207             :   // See crbug.com/539863.
     208             :   raw_addr &= 0x007fffff0000ULL;
     209             :   raw_addr += 0x7e8000000000ULL;
     210             : #else
     211             : #if V8_TARGET_ARCH_X64
     212             :   // Currently available CPUs have 48 bits of virtual addressing.  Truncate
     213             :   // the hint address to 46 bits to give the kernel a fighting chance of
     214             :   // fulfilling our placement request.
     215     2538174 :   raw_addr &= uint64_t{0x3FFFFFFFF000};
     216             : #elif V8_TARGET_ARCH_PPC64
     217             : #if V8_OS_AIX
     218             :   // AIX: 64 bits of virtual addressing, but we limit address range to:
     219             :   //   a) minimize Segment Lookaside Buffer (SLB) misses and
     220             :   raw_addr &= uint64_t{0x3FFFF000};
     221             :   // Use extra address space to isolate the mmap regions.
     222             :   raw_addr += uint64_t{0x400000000000};
     223             : #elif V8_TARGET_BIG_ENDIAN
     224             :   // Big-endian Linux: 42 bits of virtual addressing.
     225             :   raw_addr &= uint64_t{0x03FFFFFFF000};
     226             : #else
     227             :   // Little-endian Linux: 46 bits of virtual addressing.
     228             :   raw_addr &= uint64_t{0x3FFFFFFF0000};
     229             : #endif
     230             : #elif V8_TARGET_ARCH_S390X
     231             :   // Linux on Z uses bits 22-32 for Region Indexing, which translates to 42 bits
     232             :   // of virtual addressing.  Truncate to 40 bits to allow kernel chance to
     233             :   // fulfill request.
     234             :   raw_addr &= uint64_t{0xFFFFFFF000};
     235             : #elif V8_TARGET_ARCH_S390
     236             :   // 31 bits of virtual addressing.  Truncate to 29 bits to allow kernel chance
     237             :   // to fulfill request.
     238             :   raw_addr &= 0x1FFFF000;
     239             : #elif V8_TARGET_ARCH_MIPS64
     240             :   // 42 bits of virtual addressing. Truncate to 40 bits to allow kernel chance
     241             :   // to fulfill request.
     242             :   raw_addr &= uint64_t{0xFFFFFF0000};
     243             : #else
     244             :   raw_addr &= 0x3FFFF000;
     245             : 
     246             : #ifdef __sun
     247             :   // For our Solaris/illumos mmap hint, we pick a random address in the bottom
     248             :   // half of the top half of the address space (that is, the third quarter).
     249             :   // Because we do not MAP_FIXED, this will be treated only as a hint -- the
     250             :   // system will not fail to mmap() because something else happens to already
     251             :   // be mapped at our random address. We deliberately set the hint high enough
     252             :   // to get well above the system's break (that is, the heap); Solaris and
     253             :   // illumos will try the hint and if that fails allocate as if there were
     254             :   // no hint at all. The high hint prevents the break from getting hemmed in
     255             :   // at low values, ceding half of the address space to the system heap.
     256             :   raw_addr += 0x80000000;
     257             : #elif V8_OS_AIX
     258             :   // The range 0x30000000 - 0xD0000000 is available on AIX;
     259             :   // choose the upper range.
     260             :   raw_addr += 0x90000000;
     261             : #else
     262             :   // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
     263             :   // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
     264             :   // 10.6 and 10.7.
     265             :   raw_addr += 0x20000000;
     266             : #endif
     267             : #endif
     268             : #endif
     269     2538174 :   return reinterpret_cast<void*>(raw_addr);
     270             : }
     271             : 
     272             : // TODO(bbudge) Move Cygwin and Fuschia stuff into platform-specific files.
     273             : #if !V8_OS_CYGWIN && !V8_OS_FUCHSIA
     274             : // static
     275     2429378 : void* OS::Allocate(void* address, size_t size, size_t alignment,
     276             :                    MemoryPermission access) {
     277             :   size_t page_size = AllocatePageSize();
     278             :   DCHECK_EQ(0, size % page_size);
     279             :   DCHECK_EQ(0, alignment % page_size);
     280             :   address = AlignedAddress(address, alignment);
     281             :   // Add the maximum misalignment so we are guaranteed an aligned base address.
     282     2429352 :   size_t request_size = size + (alignment - page_size);
     283             :   request_size = RoundUp(request_size, OS::AllocatePageSize());
     284     2429360 :   void* result = base::Allocate(address, request_size, access);
     285     2429378 :   if (result == nullptr) return nullptr;
     286             : 
     287             :   // Unmap memory allocated before the aligned base address.
     288             :   uint8_t* base = static_cast<uint8_t*>(result);
     289             :   uint8_t* aligned_base = reinterpret_cast<uint8_t*>(
     290     4858716 :       RoundUp(reinterpret_cast<uintptr_t>(base), alignment));
     291     2429358 :   if (aligned_base != base) {
     292             :     DCHECK_LT(base, aligned_base);
     293      203173 :     size_t prefix_size = static_cast<size_t>(aligned_base - base);
     294      203173 :     CHECK(Free(base, prefix_size));
     295      203173 :     request_size -= prefix_size;
     296             :   }
     297             :   // Unmap memory allocated after the potentially unaligned end.
     298     2429358 :   if (size != request_size) {
     299             :     DCHECK_LT(size, request_size);
     300      634668 :     size_t suffix_size = request_size - size;
     301     1269336 :     CHECK(Free(aligned_base + size, suffix_size));
     302             :     request_size -= suffix_size;
     303             :   }
     304             : 
     305             :   DCHECK_EQ(size, request_size);
     306     2429358 :   return static_cast<void*>(aligned_base);
     307             : }
     308             : 
     309             : // static
     310     2429046 : bool OS::Free(void* address, const size_t size) {
     311             :   DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % AllocatePageSize());
     312             :   DCHECK_EQ(0, size % AllocatePageSize());
     313     3382329 :   return munmap(address, size) == 0;
     314             : }
     315             : 
     316             : // static
     317      125598 : bool OS::Release(void* address, size_t size) {
     318             :   DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % CommitPageSize());
     319             :   DCHECK_EQ(0, size % CommitPageSize());
     320      125598 :   return munmap(address, size) == 0;
     321             : }
     322             : 
     323             : // static
     324    11432048 : bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) {
     325             :   DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % CommitPageSize());
     326             :   DCHECK_EQ(0, size % CommitPageSize());
     327             : 
     328    11432048 :   int prot = GetProtectionFromMemoryPermission(access);
     329    11432042 :   int ret = mprotect(address, size, prot);
     330    11432079 :   if (ret == 0 && access == OS::MemoryPermission::kNoAccess) {
     331             :     // This is advisory; ignore errors and continue execution.
     332      880981 :     USE(DiscardSystemPages(address, size));
     333             :   }
     334             : 
     335             : // For accounting purposes, we want to call MADV_FREE_REUSE on macOS after
     336             : // changing permissions away from OS::MemoryPermission::kNoAccess. Since this
     337             : // state is not kept at this layer, we always call this if access != kNoAccess.
     338             : // The cost is a syscall that effectively no-ops.
     339             : // TODO(erikchen): Fix this to only call MADV_FREE_REUSE when necessary.
     340             : // https://crbug.com/823915
     341             : #if defined(OS_MACOSX)
     342             :   if (access != OS::MemoryPermission::kNoAccess)
     343             :     madvise(address, size, MADV_FREE_REUSE);
     344             : #endif
     345             : 
     346    11432077 :   return ret == 0;
     347             : }
     348             : 
     349      943984 : bool OS::DiscardSystemPages(void* address, size_t size) {
     350             :   DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % CommitPageSize());
     351             :   DCHECK_EQ(0, size % CommitPageSize());
     352             : #if defined(OS_MACOSX)
     353             :   // On OSX, MADV_FREE_REUSABLE has comparable behavior to MADV_FREE, but also
     354             :   // marks the pages with the reusable bit, which allows both Activity Monitor
     355             :   // and memory-infra to correctly track the pages.
     356             :   int ret = madvise(address, size, MADV_FREE_REUSABLE);
     357             : #elif defined(_AIX) || defined(V8_OS_SOLARIS)
     358             :   int ret = madvise(reinterpret_cast<caddr_t>(address), size, MADV_FREE);
     359             : #else
     360      943984 :   int ret = madvise(address, size, MADV_FREE);
     361             : #endif
     362      943984 :   if (ret != 0 && errno == ENOSYS)
     363             :     return true;  // madvise is not available on all systems.
     364      943980 :   if (ret != 0 && errno == EINVAL) {
     365             : // MADV_FREE only works on Linux 4.5+ . If request failed, retry with older
     366             : // MADV_DONTNEED . Note that MADV_FREE being defined at compile time doesn't
     367             : // imply runtime support.
     368             : #if defined(_AIX) || defined(V8_OS_SOLARIS)
     369             :     ret = madvise(reinterpret_cast<caddr_t>(address), size, MADV_DONTNEED);
     370             : #else
     371           0 :     ret = madvise(address, size, MADV_DONTNEED);
     372             : #endif
     373             :   }
     374      943980 :   return ret == 0;
     375             : }
     376             : 
     377             : // static
     378       13673 : bool OS::HasLazyCommits() {
     379             : #if V8_OS_AIX || V8_OS_LINUX || V8_OS_MACOSX
     380       13673 :   return true;
     381             : #else
     382             :   // TODO(bbudge) Return true for all POSIX platforms.
     383             :   return false;
     384             : #endif
     385             : }
     386             : #endif  // !V8_OS_CYGWIN && !V8_OS_FUCHSIA
     387             : 
     388           0 : const char* OS::GetGCFakeMMapFile() {
     389           0 :   return g_gc_fake_mmap;
     390             : }
     391             : 
     392             : 
     393       40601 : void OS::Sleep(TimeDelta interval) {
     394       40601 :   usleep(static_cast<useconds_t>(interval.InMicroseconds()));
     395       40601 : }
     396             : 
     397             : 
     398           0 : void OS::Abort() {
     399           0 :   if (g_hard_abort) {
     400           0 :     V8_IMMEDIATE_CRASH();
     401             :   }
     402             :   // Redirect to std abort to signal abnormal program termination.
     403           0 :   abort();
     404             : }
     405             : 
     406             : 
     407           0 : void OS::DebugBreak() {
     408             : #if V8_HOST_ARCH_ARM
     409             :   asm("bkpt 0");
     410             : #elif V8_HOST_ARCH_ARM64
     411             :   asm("brk 0");
     412             : #elif V8_HOST_ARCH_MIPS
     413             :   asm("break");
     414             : #elif V8_HOST_ARCH_MIPS64
     415             :   asm("break");
     416             : #elif V8_HOST_ARCH_PPC
     417             :   asm("twge 2,2");
     418             : #elif V8_HOST_ARCH_IA32
     419             :   asm("int $3");
     420             : #elif V8_HOST_ARCH_X64
     421           0 :   asm("int $3");
     422             : #elif V8_HOST_ARCH_S390
     423             :   // Software breakpoint instruction is 0x0001
     424             :   asm volatile(".word 0x0001");
     425             : #else
     426             : #error Unsupported host architecture.
     427             : #endif
     428           0 : }
     429             : 
     430             : 
     431             : class PosixMemoryMappedFile final : public OS::MemoryMappedFile {
     432             :  public:
     433             :   PosixMemoryMappedFile(FILE* file, void* memory, size_t size)
     434      115442 :       : file_(file), memory_(memory), size_(size) {}
     435             :   ~PosixMemoryMappedFile() final;
     436      115553 :   void* memory() const final { return memory_; }
     437      115514 :   size_t size() const final { return size_; }
     438             : 
     439             :  private:
     440             :   FILE* const file_;
     441             :   void* const memory_;
     442             :   size_t const size_;
     443             : };
     444             : 
     445             : 
     446             : // static
     447      115537 : OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
     448      115537 :   if (FILE* file = fopen(name, "r+")) {
     449      115442 :     if (fseek(file, 0, SEEK_END) == 0) {
     450      115442 :       long size = ftell(file);  // NOLINT(runtime/int)
     451      115442 :       if (size >= 0) {
     452             :         void* const memory =
     453             :             mmap(OS::GetRandomMmapAddr(), size, PROT_READ | PROT_WRITE,
     454      115442 :                  MAP_SHARED, fileno(file), 0);
     455      115442 :         if (memory != MAP_FAILED) {
     456      230884 :           return new PosixMemoryMappedFile(file, memory, size);
     457             :         }
     458             :       }
     459             :     }
     460           0 :     fclose(file);
     461             :   }
     462             :   return nullptr;
     463             : }
     464             : 
     465             : 
     466             : // static
     467           0 : OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name,
     468             :                                                    size_t size, void* initial) {
     469           0 :   if (FILE* file = fopen(name, "w+")) {
     470           0 :     size_t result = fwrite(initial, 1, size, file);
     471           0 :     if (result == size && !ferror(file)) {
     472             :       void* memory = mmap(OS::GetRandomMmapAddr(), result,
     473           0 :                           PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
     474           0 :       if (memory != MAP_FAILED) {
     475           0 :         return new PosixMemoryMappedFile(file, memory, result);
     476             :       }
     477             :     }
     478           0 :     fclose(file);
     479             :   }
     480             :   return nullptr;
     481             : }
     482             : 
     483             : 
     484      230884 : PosixMemoryMappedFile::~PosixMemoryMappedFile() {
     485      461768 :   if (memory_) CHECK(OS::Free(memory_, RoundUp(size_, OS::AllocatePageSize())));
     486      115442 :   fclose(file_);
     487      230884 : }
     488             : 
     489             : 
     490      141291 : int OS::GetCurrentProcessId() {
     491      141291 :   return static_cast<int>(getpid());
     492             : }
     493             : 
     494             : 
     495         790 : int OS::GetCurrentThreadId() {
     496             : #if V8_OS_MACOSX || (V8_OS_ANDROID && defined(__APPLE__))
     497             :   return static_cast<int>(pthread_mach_thread_np(pthread_self()));
     498             : #elif V8_OS_LINUX
     499         790 :   return static_cast<int>(syscall(__NR_gettid));
     500             : #elif V8_OS_ANDROID
     501             :   return static_cast<int>(gettid());
     502             : #elif V8_OS_AIX
     503             :   return static_cast<int>(thread_self());
     504             : #elif V8_OS_FUCHSIA
     505             :   return static_cast<int>(zx_thread_self());
     506             : #elif V8_OS_SOLARIS
     507             :   return static_cast<int>(pthread_self());
     508             : #else
     509             :   return static_cast<int>(reinterpret_cast<intptr_t>(pthread_self()));
     510             : #endif
     511             : }
     512             : 
     513           0 : void OS::ExitProcess(int exit_code) {
     514             :   // Use _exit instead of exit to avoid races between isolate
     515             :   // threads and static destructors.
     516           0 :   fflush(stdout);
     517           0 :   fflush(stderr);
     518           0 :   _exit(exit_code);
     519             : }
     520             : 
     521             : // ----------------------------------------------------------------------------
     522             : // POSIX date/time support.
     523             : //
     524             : 
     525             : #if !defined(V8_OS_FUCHSIA)
     526          64 : int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
     527             :   struct rusage usage;
     528             : 
     529          64 :   if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
     530          64 :   *secs = static_cast<uint32_t>(usage.ru_utime.tv_sec);
     531          64 :   *usecs = static_cast<uint32_t>(usage.ru_utime.tv_usec);
     532          64 :   return 0;
     533             : }
     534             : #endif
     535             : 
     536      165476 : double OS::TimeCurrentMillis() {
     537      165476 :   return Time::Now().ToJsTime();
     538             : }
     539             : 
     540         225 : double PosixTimezoneCache::DaylightSavingsOffset(double time) {
     541         225 :   if (std::isnan(time)) return std::numeric_limits<double>::quiet_NaN();
     542         225 :   time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
     543             :   struct tm tm;
     544         225 :   struct tm* t = localtime_r(&tv, &tm);
     545         225 :   if (nullptr == t) return std::numeric_limits<double>::quiet_NaN();
     546         225 :   return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
     547             : }
     548             : 
     549             : 
     550          15 : int OS::GetLastError() {
     551          15 :   return errno;
     552             : }
     553             : 
     554             : 
     555             : // ----------------------------------------------------------------------------
     556             : // POSIX stdio support.
     557             : //
     558             : 
     559        2337 : FILE* OS::FOpen(const char* path, const char* mode) {
     560        2337 :   FILE* file = fopen(path, mode);
     561        2337 :   if (file == nullptr) return nullptr;
     562             :   struct stat file_stat;
     563        4674 :   if (fstat(fileno(file), &file_stat) != 0) {
     564           0 :     fclose(file);
     565           0 :     return nullptr;
     566             :   }
     567        2337 :   bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
     568        2337 :   if (is_regular_file) return file;
     569           0 :   fclose(file);
     570           0 :   return nullptr;
     571             : }
     572             : 
     573             : 
     574           0 : bool OS::Remove(const char* path) {
     575           0 :   return (remove(path) == 0);
     576             : }
     577             : 
     578           2 : char OS::DirectorySeparator() { return '/'; }
     579             : 
     580     1721508 : bool OS::isDirectorySeparator(const char ch) {
     581     1721508 :   return ch == DirectorySeparator();
     582             : }
     583             : 
     584             : 
     585          61 : FILE* OS::OpenTemporaryFile() {
     586          61 :   return tmpfile();
     587             : }
     588             : 
     589             : 
     590             : const char* const OS::LogFileOpenMode = "w";
     591             : 
     592             : 
     593        4581 : void OS::Print(const char* format, ...) {
     594             :   va_list args;
     595        4581 :   va_start(args, format);
     596             :   VPrint(format, args);
     597        4581 :   va_end(args);
     598        4581 : }
     599             : 
     600             : 
     601      140257 : void OS::VPrint(const char* format, va_list args) {
     602             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     603             :   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
     604             : #else
     605             :   vprintf(format, args);
     606             : #endif
     607      140257 : }
     608             : 
     609             : 
     610           0 : void OS::FPrint(FILE* out, const char* format, ...) {
     611             :   va_list args;
     612           0 :   va_start(args, format);
     613             :   VFPrint(out, format, args);
     614           0 :   va_end(args);
     615           0 : }
     616             : 
     617             : 
     618     3495677 : void OS::VFPrint(FILE* out, const char* format, va_list args) {
     619             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     620             :   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
     621             : #else
     622             :   vfprintf(out, format, args);
     623             : #endif
     624     3495677 : }
     625             : 
     626             : 
     627          95 : void OS::PrintError(const char* format, ...) {
     628             :   va_list args;
     629          95 :   va_start(args, format);
     630             :   VPrintError(format, args);
     631          95 :   va_end(args);
     632          95 : }
     633             : 
     634             : 
     635           0 : void OS::VPrintError(const char* format, va_list args) {
     636             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     637             :   __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
     638             : #else
     639          95 :   vfprintf(stderr, format, args);
     640             : #endif
     641           0 : }
     642             : 
     643             : 
     644      410507 : int OS::SNPrintF(char* str, int length, const char* format, ...) {
     645             :   va_list args;
     646      410507 :   va_start(args, format);
     647      410507 :   int result = VSNPrintF(str, length, format, args);
     648      410507 :   va_end(args);
     649      410507 :   return result;
     650             : }
     651             : 
     652             : 
     653     7225015 : int OS::VSNPrintF(char* str,
     654             :                   int length,
     655             :                   const char* format,
     656             :                   va_list args) {
     657     7225015 :   int n = vsnprintf(str, length, format, args);
     658     7225015 :   if (n < 0 || n >= length) {
     659             :     // If the length is zero, the assignment fails.
     660      184875 :     if (length > 0)
     661      184875 :       str[length - 1] = '\0';
     662             :     return -1;
     663             :   } else {
     664             :     return n;
     665             :   }
     666             : }
     667             : 
     668             : 
     669             : // ----------------------------------------------------------------------------
     670             : // POSIX string support.
     671             : //
     672             : 
     673           0 : char* OS::StrChr(char* str, int c) {
     674           0 :   return strchr(str, c);
     675             : }
     676             : 
     677             : 
     678       25986 : void OS::StrNCpy(char* dest, int length, const char* src, size_t n) {
     679             :   strncpy(dest, src, n);
     680       25986 : }
     681             : 
     682             : 
     683             : // ----------------------------------------------------------------------------
     684             : // POSIX thread support.
     685             : //
     686             : 
     687      497629 : class Thread::PlatformData {
     688             :  public:
     689      519353 :   PlatformData() : thread_(kNoThread) {}
     690             :   pthread_t thread_;  // Thread handle for pthread.
     691             :   // Synchronizes thread creation
     692             :   Mutex thread_creation_mutex_;
     693             : };
     694             : 
     695     1558059 : Thread::Thread(const Options& options)
     696             :     : data_(new PlatformData),
     697             :       stack_size_(options.stack_size()),
     698     1558059 :       start_semaphore_(nullptr) {
     699      519353 :   if (stack_size_ > 0 && static_cast<size_t>(stack_size_) < PTHREAD_STACK_MIN) {
     700           0 :     stack_size_ = PTHREAD_STACK_MIN;
     701             :   }
     702             :   set_name(options.name());
     703      519353 : }
     704             : 
     705             : 
     706      497629 : Thread::~Thread() {
     707      995258 :   delete data_;
     708      497629 : }
     709             : 
     710             : 
     711             : static void SetThreadName(const char* name) {
     712             : #if V8_OS_DRAGONFLYBSD || V8_OS_FREEBSD || V8_OS_OPENBSD
     713             :   pthread_set_name_np(pthread_self(), name);
     714             : #elif V8_OS_NETBSD
     715             :   STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP);
     716             :   pthread_setname_np(pthread_self(), "%s", name);
     717             : #elif V8_OS_MACOSX
     718             :   // pthread_setname_np is only available in 10.6 or later, so test
     719             :   // for it at runtime.
     720             :   int (*dynamic_pthread_setname_np)(const char*);
     721             :   *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
     722             :     dlsym(RTLD_DEFAULT, "pthread_setname_np");
     723             :   if (dynamic_pthread_setname_np == nullptr) return;
     724             : 
     725             :   // Mac OS X does not expose the length limit of the name, so hardcode it.
     726             :   static const int kMaxNameLength = 63;
     727             :   STATIC_ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength);
     728             :   dynamic_pthread_setname_np(name);
     729             : #elif defined(PR_SET_NAME)
     730             :   prctl(PR_SET_NAME,
     731             :         reinterpret_cast<unsigned long>(name),  // NOLINT
     732      456386 :         0, 0, 0);
     733             : #endif
     734             : }
     735             : 
     736             : 
     737      456089 : static void* ThreadEntry(void* arg) {
     738      456089 :   Thread* thread = reinterpret_cast<Thread*>(arg);
     739             :   // We take the lock here to make sure that pthread_create finished first since
     740             :   // we don't know which thread will run first (the original thread or the new
     741             :   // one).
     742      456089 :   { MutexGuard lock_guard(&thread->data()->thread_creation_mutex_); }
     743      456386 :   SetThreadName(thread->name());
     744             :   DCHECK_NE(thread->data()->thread_, kNoThread);
     745      455948 :   thread->NotifyStartedAndRun();
     746      435200 :   return nullptr;
     747             : }
     748             : 
     749             : 
     750           0 : void Thread::set_name(const char* name) {
     751      519353 :   strncpy(name_, name, sizeof(name_));
     752      519353 :   name_[sizeof(name_) - 1] = '\0';
     753           0 : }
     754             : 
     755             : 
     756      456465 : void Thread::Start() {
     757             :   int result;
     758             :   pthread_attr_t attr;
     759             :   memset(&attr, 0, sizeof(attr));
     760      456465 :   result = pthread_attr_init(&attr);
     761             :   DCHECK_EQ(0, result);
     762      456465 :   size_t stack_size = stack_size_;
     763             :   if (stack_size == 0) {
     764             : #if V8_OS_MACOSX
     765             :     // Default on Mac OS X is 512kB -- bump up to 1MB
     766             :     stack_size = 1 * 1024 * 1024;
     767             : #elif V8_OS_AIX
     768             :     // Default on AIX is 96kB -- bump up to 2MB
     769             :     stack_size = 2 * 1024 * 1024;
     770             : #endif
     771             :   }
     772      456465 :   if (stack_size > 0) {
     773       13724 :     result = pthread_attr_setstacksize(&attr, stack_size);
     774             :     DCHECK_EQ(0, result);
     775             :   }
     776             :   {
     777      456465 :     MutexGuard lock_guard(&data_->thread_creation_mutex_);
     778      456465 :     result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
     779             :   }
     780             :   DCHECK_EQ(0, result);
     781      456465 :   result = pthread_attr_destroy(&attr);
     782             :   DCHECK_EQ(0, result);
     783             :   DCHECK_NE(data_->thread_, kNoThread);
     784             :   USE(result);
     785      456465 : }
     786             : 
     787      439130 : void Thread::Join() { pthread_join(data_->thread_, nullptr); }
     788             : 
     789             : static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
     790             : #if V8_OS_CYGWIN
     791             :   // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
     792             :   // because pthread_key_t is a pointer type on Cygwin. This will probably not
     793             :   // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
     794             :   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
     795             :   intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key);
     796             :   return static_cast<Thread::LocalStorageKey>(ptr_key);
     797             : #else
     798      244967 :   return static_cast<Thread::LocalStorageKey>(pthread_key);
     799             : #endif
     800             : }
     801             : 
     802             : 
     803             : static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
     804             : #if V8_OS_CYGWIN
     805             :   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
     806             :   intptr_t ptr_key = static_cast<intptr_t>(local_key);
     807             :   return reinterpret_cast<pthread_key_t>(ptr_key);
     808             : #else
     809     3348127 :   return static_cast<pthread_key_t>(local_key);
     810             : #endif
     811             : }
     812             : 
     813             : 
     814             : #ifdef V8_FAST_TLS_SUPPORTED
     815             : 
     816             : static Atomic32 tls_base_offset_initialized = 0;
     817             : intptr_t kMacTlsBaseOffset = 0;
     818             : 
     819             : // It's safe to do the initialization more that once, but it has to be
     820             : // done at least once.
     821             : static void InitializeTlsBaseOffset() {
     822             :   const size_t kBufferSize = 128;
     823             :   char buffer[kBufferSize];
     824             :   size_t buffer_size = kBufferSize;
     825             :   int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
     826             :   if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
     827             :     FATAL("V8 failed to get kernel version");
     828             :   }
     829             :   // The buffer now contains a string of the form XX.YY.ZZ, where
     830             :   // XX is the major kernel version component.
     831             :   // Make sure the buffer is 0-terminated.
     832             :   buffer[kBufferSize - 1] = '\0';
     833             :   char* period_pos = strchr(buffer, '.');
     834             :   *period_pos = '\0';
     835             :   int kernel_version_major =
     836             :       static_cast<int>(strtol(buffer, nullptr, 10));  // NOLINT
     837             :   // The constants below are taken from pthreads.s from the XNU kernel
     838             :   // sources archive at www.opensource.apple.com.
     839             :   if (kernel_version_major < 11) {
     840             :     // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the
     841             :     // same offsets.
     842             : #if V8_HOST_ARCH_IA32
     843             :     kMacTlsBaseOffset = 0x48;
     844             : #else
     845             :     kMacTlsBaseOffset = 0x60;
     846             : #endif
     847             :   } else {
     848             :     // 11.x.x (Lion) changed the offset.
     849             :     kMacTlsBaseOffset = 0;
     850             :   }
     851             : 
     852             :   Release_Store(&tls_base_offset_initialized, 1);
     853             : }
     854             : 
     855             : 
     856             : static void CheckFastTls(Thread::LocalStorageKey key) {
     857             :   void* expected = reinterpret_cast<void*>(0x1234CAFE);
     858             :   Thread::SetThreadLocal(key, expected);
     859             :   void* actual = Thread::GetExistingThreadLocal(key);
     860             :   if (expected != actual) {
     861             :     FATAL("V8 failed to initialize fast TLS on current kernel");
     862             :   }
     863             :   Thread::SetThreadLocal(key, nullptr);
     864             : }
     865             : 
     866             : #endif  // V8_FAST_TLS_SUPPORTED
     867             : 
     868             : 
     869      244965 : Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
     870             : #ifdef V8_FAST_TLS_SUPPORTED
     871             :   bool check_fast_tls = false;
     872             :   if (tls_base_offset_initialized == 0) {
     873             :     check_fast_tls = true;
     874             :     InitializeTlsBaseOffset();
     875             :   }
     876             : #endif
     877             :   pthread_key_t key;
     878      244965 :   int result = pthread_key_create(&key, nullptr);
     879             :   DCHECK_EQ(0, result);
     880             :   USE(result);
     881      244967 :   LocalStorageKey local_key = PthreadKeyToLocalKey(key);
     882             : #ifdef V8_FAST_TLS_SUPPORTED
     883             :   // If we just initialized fast TLS support, make sure it works.
     884             :   if (check_fast_tls) CheckFastTls(local_key);
     885             : #endif
     886      244967 :   return local_key;
     887             : }
     888             : 
     889             : 
     890       62899 : void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
     891             :   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
     892       62899 :   int result = pthread_key_delete(pthread_key);
     893             :   DCHECK_EQ(0, result);
     894             :   USE(result);
     895       62900 : }
     896             : 
     897             : 
     898     1972926 : void* Thread::GetThreadLocal(LocalStorageKey key) {
     899             :   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
     900     1972926 :   return pthread_getspecific(pthread_key);
     901             : }
     902             : 
     903             : 
     904     1312302 : void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
     905             :   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
     906     1312302 :   int result = pthread_setspecific(pthread_key, value);
     907             :   DCHECK_EQ(0, result);
     908             :   USE(result);
     909     1312298 : }
     910             : 
     911             : #undef LOG_TAG
     912             : #undef MAP_ANONYMOUS
     913             : #undef MADV_FREE
     914             : 
     915             : }  // namespace base
     916             : }  // namespace v8

Generated by: LCOV version 1.10