LCOV - code coverage report
Current view: top level - src/base/platform - platform-posix.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 178 220 80.9 %
Date: 2019-02-19 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     2336621 : 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    12541272 : int GetProtectionFromMemoryPermission(OS::MemoryPermission access) {
     112    12541272 :   switch (access) {
     113             :     case OS::MemoryPermission::kNoAccess:
     114             :       return PROT_NONE;
     115             :     case OS::MemoryPermission::kRead:
     116      145235 :       return PROT_READ;
     117             :     case OS::MemoryPermission::kReadWrite:
     118     4620191 :       return PROT_READ | PROT_WRITE;
     119             :     case OS::MemoryPermission::kReadWriteExecute:
     120     1244467 :       return PROT_READ | PROT_WRITE | PROT_EXEC;
     121             :     case OS::MemoryPermission::kReadExecute:
     122     3582178 :       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     2087543 :   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     2087543 : void* Allocate(void* address, size_t size, OS::MemoryPermission access) {
     141     2087543 :   int prot = GetProtectionFromMemoryPermission(access);
     142             :   int flags = GetFlagsForMemoryPermission(access);
     143     2087543 :   void* result = mmap(address, size, prot, flags, kMmapFd, kMmapFdOffset);
     144     2087549 :   if (result == MAP_FAILED) return nullptr;
     145     2087529 :   return result;
     146             : }
     147             : 
     148             : #endif  // !V8_OS_FUCHSIA
     149             : 
     150             : }  // namespace
     151             : 
     152       59583 : void OS::Initialize(bool hard_abort, const char* const gc_fake_mmap) {
     153       59583 :   g_hard_abort = hard_abort;
     154       59583 :   g_gc_fake_mmap = gc_fake_mmap;
     155       59583 : }
     156             : 
     157      762580 : 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      762580 :   return 16;
     173             : #endif
     174             : }
     175             : 
     176             : // static
     177       59619 : size_t OS::AllocatePageSize() {
     178     4348473 :   return static_cast<size_t>(sysconf(_SC_PAGESIZE));
     179             : }
     180             : 
     181             : // static
     182       59619 : size_t OS::CommitPageSize() {
     183       59619 :   static size_t page_size = getpagesize();
     184       59619 :   return page_size;
     185             : }
     186             : 
     187             : // static
     188       58099 : void OS::SetRandomMmapSeed(int64_t seed) {
     189       58099 :   if (seed) {
     190             :     MutexGuard guard(rng_mutex.Pointer());
     191       58099 :     GetPlatformRandomNumberGenerator()->SetSeed(seed);
     192             :   }
     193       58099 : }
     194             : 
     195             : // static
     196     2218934 : void* OS::GetRandomMmapAddr() {
     197             :   uintptr_t raw_addr;
     198             :   {
     199             :     MutexGuard guard(rng_mutex.Pointer());
     200     2218943 :     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     2218943 :   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     2218943 :   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     2087547 : 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     2087542 :   size_t request_size = size + (alignment - page_size);
     283             :   request_size = RoundUp(request_size, OS::AllocatePageSize());
     284     2087544 :   void* result = base::Allocate(address, request_size, access);
     285     2087549 :   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     4175058 :       RoundUp(reinterpret_cast<uintptr_t>(base), alignment));
     291     2087529 :   if (aligned_base != base) {
     292             :     DCHECK_LT(base, aligned_base);
     293      176893 :     size_t prefix_size = static_cast<size_t>(aligned_base - base);
     294      176893 :     CHECK(Free(base, prefix_size));
     295      176893 :     request_size -= prefix_size;
     296             :   }
     297             :   // Unmap memory allocated after the potentially unaligned end.
     298     2087529 :   if (size != request_size) {
     299             :     DCHECK_LT(size, request_size);
     300      611538 :     size_t suffix_size = request_size - size;
     301     1223076 :     CHECK(Free(aligned_base + size, suffix_size));
     302             :     request_size -= suffix_size;
     303             :   }
     304             : 
     305             :   DCHECK_EQ(size, request_size);
     306     2087529 :   return static_cast<void*>(aligned_base);
     307             : }
     308             : 
     309             : // static
     310     2087277 : 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     2989473 :   return munmap(address, size) == 0;
     314             : }
     315             : 
     316             : // static
     317      121932 : 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      121932 :   return munmap(address, size) == 0;
     321             : }
     322             : 
     323             : // static
     324    10453733 : 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    10453733 :   int prot = GetProtectionFromMemoryPermission(access);
     329    10453731 :   int ret = mprotect(address, size, prot);
     330    10453749 :   if (ret == 0 && access == OS::MemoryPermission::kNoAccess) {
     331             :     // This is advisory; ignore errors and continue execution.
     332      863791 :     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    10453749 :   return ret == 0;
     347             : }
     348             : 
     349      918491 : 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      918491 :   int ret = madvise(address, size, MADV_FREE);
     361             : #endif
     362      918489 :   if (ret != 0 && errno == ENOSYS)
     363             :     return true;  // madvise is not available on all systems.
     364      918487 :   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      918487 :   return ret == 0;
     375             : }
     376             : 
     377             : // static
     378       13519 : bool OS::HasLazyCommits() {
     379             : #if V8_OS_AIX || V8_OS_LINUX || V8_OS_MACOSX
     380       13519 :   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       12917 : void OS::Sleep(TimeDelta interval) {
     394       12917 :   usleep(static_cast<useconds_t>(interval.InMicroseconds()));
     395       12917 : }
     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      113774 :       : file_(file), memory_(memory), size_(size) {}
     435             :   ~PosixMemoryMappedFile() final;
     436      113885 :   void* memory() const final { return memory_; }
     437      113846 :   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      113868 : OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
     448      113868 :   if (FILE* file = fopen(name, "r+")) {
     449      113774 :     if (fseek(file, 0, SEEK_END) == 0) {
     450      113774 :       long size = ftell(file);  // NOLINT(runtime/int)
     451      113783 :       if (size == 0) return new PosixMemoryMappedFile(file, nullptr, 0);
     452      113765 :       if (size > 0) {
     453             :         void* const memory =
     454             :             mmap(OS::GetRandomMmapAddr(), size, PROT_READ | PROT_WRITE,
     455      113765 :                  MAP_SHARED, fileno(file), 0);
     456      113765 :         if (memory != MAP_FAILED) {
     457      227530 :           return new PosixMemoryMappedFile(file, memory, size);
     458             :         }
     459             :       }
     460             :     }
     461           0 :     fclose(file);
     462             :   }
     463             :   return nullptr;
     464             : }
     465             : 
     466             : 
     467             : // static
     468           0 : OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name,
     469             :                                                    size_t size, void* initial) {
     470           0 :   if (FILE* file = fopen(name, "w+")) {
     471           0 :     if (size == 0) return new PosixMemoryMappedFile(file, 0, 0);
     472           0 :     size_t result = fwrite(initial, 1, size, file);
     473           0 :     if (result == size && !ferror(file)) {
     474             :       void* memory = mmap(OS::GetRandomMmapAddr(), result,
     475           0 :                           PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
     476           0 :       if (memory != MAP_FAILED) {
     477           0 :         return new PosixMemoryMappedFile(file, memory, result);
     478             :       }
     479             :     }
     480           0 :     fclose(file);
     481             :   }
     482             :   return nullptr;
     483             : }
     484             : 
     485             : 
     486      227548 : PosixMemoryMappedFile::~PosixMemoryMappedFile() {
     487      455069 :   if (memory_) CHECK(OS::Free(memory_, RoundUp(size_, OS::AllocatePageSize())));
     488      113774 :   fclose(file_);
     489      227548 : }
     490             : 
     491             : 
     492      129674 : int OS::GetCurrentProcessId() {
     493      129674 :   return static_cast<int>(getpid());
     494             : }
     495             : 
     496             : 
     497         790 : int OS::GetCurrentThreadId() {
     498             : #if V8_OS_MACOSX || (V8_OS_ANDROID && defined(__APPLE__))
     499             :   return static_cast<int>(pthread_mach_thread_np(pthread_self()));
     500             : #elif V8_OS_LINUX
     501         790 :   return static_cast<int>(syscall(__NR_gettid));
     502             : #elif V8_OS_ANDROID
     503             :   return static_cast<int>(gettid());
     504             : #elif V8_OS_AIX
     505             :   return static_cast<int>(thread_self());
     506             : #elif V8_OS_FUCHSIA
     507             :   return static_cast<int>(zx_thread_self());
     508             : #elif V8_OS_SOLARIS
     509             :   return static_cast<int>(pthread_self());
     510             : #else
     511             :   return static_cast<int>(reinterpret_cast<intptr_t>(pthread_self()));
     512             : #endif
     513             : }
     514             : 
     515           0 : void OS::ExitProcess(int exit_code) {
     516             :   // Use _exit instead of exit to avoid races between isolate
     517             :   // threads and static destructors.
     518           0 :   fflush(stdout);
     519           0 :   fflush(stderr);
     520           0 :   _exit(exit_code);
     521             : }
     522             : 
     523             : // ----------------------------------------------------------------------------
     524             : // POSIX date/time support.
     525             : //
     526             : 
     527             : #if !defined(V8_OS_FUCHSIA)
     528          44 : int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
     529             :   struct rusage usage;
     530             : 
     531          44 :   if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
     532          44 :   *secs = static_cast<uint32_t>(usage.ru_utime.tv_sec);
     533          44 :   *usecs = static_cast<uint32_t>(usage.ru_utime.tv_usec);
     534          44 :   return 0;
     535             : }
     536             : #endif
     537             : 
     538      165177 : double OS::TimeCurrentMillis() {
     539      165177 :   return Time::Now().ToJsTime();
     540             : }
     541             : 
     542         225 : double PosixTimezoneCache::DaylightSavingsOffset(double time) {
     543         225 :   if (std::isnan(time)) return std::numeric_limits<double>::quiet_NaN();
     544         225 :   time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
     545             :   struct tm tm;
     546         225 :   struct tm* t = localtime_r(&tv, &tm);
     547         225 :   if (nullptr == t) return std::numeric_limits<double>::quiet_NaN();
     548         225 :   return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
     549             : }
     550             : 
     551             : 
     552          15 : int OS::GetLastError() {
     553          15 :   return errno;
     554             : }
     555             : 
     556             : 
     557             : // ----------------------------------------------------------------------------
     558             : // POSIX stdio support.
     559             : //
     560             : 
     561        2245 : FILE* OS::FOpen(const char* path, const char* mode) {
     562        2245 :   FILE* file = fopen(path, mode);
     563        2245 :   if (file == nullptr) return nullptr;
     564             :   struct stat file_stat;
     565        4490 :   if (fstat(fileno(file), &file_stat) != 0) {
     566           0 :     fclose(file);
     567           0 :     return nullptr;
     568             :   }
     569        2245 :   bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
     570        2245 :   if (is_regular_file) return file;
     571           0 :   fclose(file);
     572           0 :   return nullptr;
     573             : }
     574             : 
     575             : 
     576           0 : bool OS::Remove(const char* path) {
     577           0 :   return (remove(path) == 0);
     578             : }
     579             : 
     580           2 : char OS::DirectorySeparator() { return '/'; }
     581             : 
     582     1654139 : bool OS::isDirectorySeparator(const char ch) {
     583     1654139 :   return ch == DirectorySeparator();
     584             : }
     585             : 
     586             : 
     587          60 : FILE* OS::OpenTemporaryFile() {
     588          60 :   return tmpfile();
     589             : }
     590             : 
     591             : 
     592             : const char* const OS::LogFileOpenMode = "w";
     593             : 
     594             : 
     595        4693 : void OS::Print(const char* format, ...) {
     596             :   va_list args;
     597        4693 :   va_start(args, format);
     598             :   VPrint(format, args);
     599        4693 :   va_end(args);
     600        4693 : }
     601             : 
     602             : 
     603      141209 : void OS::VPrint(const char* format, va_list args) {
     604             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     605             :   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
     606             : #else
     607             :   vprintf(format, args);
     608             : #endif
     609      141209 : }
     610             : 
     611             : 
     612           0 : void OS::FPrint(FILE* out, const char* format, ...) {
     613             :   va_list args;
     614           0 :   va_start(args, format);
     615             :   VFPrint(out, format, args);
     616           0 :   va_end(args);
     617           0 : }
     618             : 
     619             : 
     620     3490944 : void OS::VFPrint(FILE* out, const char* format, va_list args) {
     621             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     622             :   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
     623             : #else
     624             :   vfprintf(out, format, args);
     625             : #endif
     626     3490944 : }
     627             : 
     628             : 
     629          95 : void OS::PrintError(const char* format, ...) {
     630             :   va_list args;
     631          95 :   va_start(args, format);
     632             :   VPrintError(format, args);
     633          95 :   va_end(args);
     634          95 : }
     635             : 
     636             : 
     637           0 : void OS::VPrintError(const char* format, va_list args) {
     638             : #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     639             :   __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
     640             : #else
     641          95 :   vfprintf(stderr, format, args);
     642             : #endif
     643           0 : }
     644             : 
     645             : 
     646      404668 : int OS::SNPrintF(char* str, int length, const char* format, ...) {
     647             :   va_list args;
     648      404668 :   va_start(args, format);
     649      404668 :   int result = VSNPrintF(str, length, format, args);
     650      404668 :   va_end(args);
     651      404668 :   return result;
     652             : }
     653             : 
     654             : 
     655     6660593 : int OS::VSNPrintF(char* str,
     656             :                   int length,
     657             :                   const char* format,
     658             :                   va_list args) {
     659     6660593 :   int n = vsnprintf(str, length, format, args);
     660     6660593 :   if (n < 0 || n >= length) {
     661             :     // If the length is zero, the assignment fails.
     662      171905 :     if (length > 0)
     663      171905 :       str[length - 1] = '\0';
     664             :     return -1;
     665             :   } else {
     666             :     return n;
     667             :   }
     668             : }
     669             : 
     670             : 
     671             : // ----------------------------------------------------------------------------
     672             : // POSIX string support.
     673             : //
     674             : 
     675           0 : char* OS::StrChr(char* str, int c) {
     676           0 :   return strchr(str, c);
     677             : }
     678             : 
     679             : 
     680       25836 : void OS::StrNCpy(char* dest, int length, const char* src, size_t n) {
     681             :   strncpy(dest, src, n);
     682       25836 : }
     683             : 
     684             : 
     685             : // ----------------------------------------------------------------------------
     686             : // POSIX thread support.
     687             : //
     688             : 
     689      483048 : class Thread::PlatformData {
     690             :  public:
     691      504830 :   PlatformData() : thread_(kNoThread) {}
     692             :   pthread_t thread_;  // Thread handle for pthread.
     693             :   // Synchronizes thread creation
     694             :   Mutex thread_creation_mutex_;
     695             : };
     696             : 
     697     1514490 : Thread::Thread(const Options& options)
     698             :     : data_(new PlatformData),
     699             :       stack_size_(options.stack_size()),
     700     1514490 :       start_semaphore_(nullptr) {
     701      504830 :   if (stack_size_ > 0 && static_cast<size_t>(stack_size_) < PTHREAD_STACK_MIN) {
     702           0 :     stack_size_ = PTHREAD_STACK_MIN;
     703             :   }
     704             :   set_name(options.name());
     705      504830 : }
     706             : 
     707             : 
     708      483048 : Thread::~Thread() {
     709      966096 :   delete data_;
     710      483048 : }
     711             : 
     712             : 
     713             : static void SetThreadName(const char* name) {
     714             : #if V8_OS_DRAGONFLYBSD || V8_OS_FREEBSD || V8_OS_OPENBSD
     715             :   pthread_set_name_np(pthread_self(), name);
     716             : #elif V8_OS_NETBSD
     717             :   STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP);
     718             :   pthread_setname_np(pthread_self(), "%s", name);
     719             : #elif V8_OS_MACOSX
     720             :   // pthread_setname_np is only available in 10.6 or later, so test
     721             :   // for it at runtime.
     722             :   int (*dynamic_pthread_setname_np)(const char*);
     723             :   *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
     724             :     dlsym(RTLD_DEFAULT, "pthread_setname_np");
     725             :   if (dynamic_pthread_setname_np == nullptr) return;
     726             : 
     727             :   // Mac OS X does not expose the length limit of the name, so hardcode it.
     728             :   static const int kMaxNameLength = 63;
     729             :   STATIC_ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength);
     730             :   dynamic_pthread_setname_np(name);
     731             : #elif defined(PR_SET_NAME)
     732             :   prctl(PR_SET_NAME,
     733             :         reinterpret_cast<unsigned long>(name),  // NOLINT
     734      443715 :         0, 0, 0);
     735             : #endif
     736             : }
     737             : 
     738             : 
     739      443449 : static void* ThreadEntry(void* arg) {
     740      443449 :   Thread* thread = reinterpret_cast<Thread*>(arg);
     741             :   // We take the lock here to make sure that pthread_create finished first since
     742             :   // we don't know which thread will run first (the original thread or the new
     743             :   // one).
     744      443449 :   { MutexGuard lock_guard(&thread->data()->thread_creation_mutex_); }
     745      443715 :   SetThreadName(thread->name());
     746             :   DCHECK_NE(thread->data()->thread_, kNoThread);
     747      443355 :   thread->NotifyStartedAndRun();
     748      422450 :   return nullptr;
     749             : }
     750             : 
     751             : 
     752           0 : void Thread::set_name(const char* name) {
     753      504830 :   strncpy(name_, name, sizeof(name_));
     754      504830 :   name_[sizeof(name_) - 1] = '\0';
     755           0 : }
     756             : 
     757             : 
     758      443776 : void Thread::Start() {
     759             :   int result;
     760             :   pthread_attr_t attr;
     761             :   memset(&attr, 0, sizeof(attr));
     762      443776 :   result = pthread_attr_init(&attr);
     763             :   DCHECK_EQ(0, result);
     764      443776 :   size_t stack_size = stack_size_;
     765             :   if (stack_size == 0) {
     766             : #if V8_OS_MACOSX
     767             :     // Default on Mac OS X is 512kB -- bump up to 1MB
     768             :     stack_size = 1 * 1024 * 1024;
     769             : #elif V8_OS_AIX
     770             :     // Default on AIX is 96kB -- bump up to 2MB
     771             :     stack_size = 2 * 1024 * 1024;
     772             : #endif
     773             :   }
     774      443776 :   if (stack_size > 0) {
     775       13756 :     result = pthread_attr_setstacksize(&attr, stack_size);
     776             :     DCHECK_EQ(0, result);
     777             :   }
     778             :   {
     779      443776 :     MutexGuard lock_guard(&data_->thread_creation_mutex_);
     780      443776 :     result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
     781             :   }
     782             :   DCHECK_EQ(0, result);
     783      443776 :   result = pthread_attr_destroy(&attr);
     784             :   DCHECK_EQ(0, result);
     785             :   DCHECK_NE(data_->thread_, kNoThread);
     786             :   USE(result);
     787      443776 : }
     788             : 
     789      426297 : void Thread::Join() { pthread_join(data_->thread_, nullptr); }
     790             : 
     791             : static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
     792             : #if V8_OS_CYGWIN
     793             :   // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
     794             :   // because pthread_key_t is a pointer type on Cygwin. This will probably not
     795             :   // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
     796             :   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
     797             :   intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key);
     798             :   return static_cast<Thread::LocalStorageKey>(ptr_key);
     799             : #else
     800      176978 :   return static_cast<Thread::LocalStorageKey>(pthread_key);
     801             : #endif
     802             : }
     803             : 
     804             : 
     805             : static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
     806             : #if V8_OS_CYGWIN
     807             :   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
     808             :   intptr_t ptr_key = static_cast<intptr_t>(local_key);
     809             :   return reinterpret_cast<pthread_key_t>(ptr_key);
     810             : #else
     811     3209779 :   return static_cast<pthread_key_t>(local_key);
     812             : #endif
     813             : }
     814             : 
     815             : 
     816             : #ifdef V8_FAST_TLS_SUPPORTED
     817             : 
     818             : static Atomic32 tls_base_offset_initialized = 0;
     819             : intptr_t kMacTlsBaseOffset = 0;
     820             : 
     821             : // It's safe to do the initialization more that once, but it has to be
     822             : // done at least once.
     823             : static void InitializeTlsBaseOffset() {
     824             :   const size_t kBufferSize = 128;
     825             :   char buffer[kBufferSize];
     826             :   size_t buffer_size = kBufferSize;
     827             :   int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
     828             :   if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) {
     829             :     FATAL("V8 failed to get kernel version");
     830             :   }
     831             :   // The buffer now contains a string of the form XX.YY.ZZ, where
     832             :   // XX is the major kernel version component.
     833             :   // Make sure the buffer is 0-terminated.
     834             :   buffer[kBufferSize - 1] = '\0';
     835             :   char* period_pos = strchr(buffer, '.');
     836             :   *period_pos = '\0';
     837             :   int kernel_version_major =
     838             :       static_cast<int>(strtol(buffer, nullptr, 10));  // NOLINT
     839             :   // The constants below are taken from pthreads.s from the XNU kernel
     840             :   // sources archive at www.opensource.apple.com.
     841             :   if (kernel_version_major < 11) {
     842             :     // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the
     843             :     // same offsets.
     844             : #if V8_HOST_ARCH_IA32
     845             :     kMacTlsBaseOffset = 0x48;
     846             : #else
     847             :     kMacTlsBaseOffset = 0x60;
     848             : #endif
     849             :   } else {
     850             :     // 11.x.x (Lion) changed the offset.
     851             :     kMacTlsBaseOffset = 0;
     852             :   }
     853             : 
     854             :   Release_Store(&tls_base_offset_initialized, 1);
     855             : }
     856             : 
     857             : 
     858             : static void CheckFastTls(Thread::LocalStorageKey key) {
     859             :   void* expected = reinterpret_cast<void*>(0x1234CAFE);
     860             :   Thread::SetThreadLocal(key, expected);
     861             :   void* actual = Thread::GetExistingThreadLocal(key);
     862             :   if (expected != actual) {
     863             :     FATAL("V8 failed to initialize fast TLS on current kernel");
     864             :   }
     865             :   Thread::SetThreadLocal(key, nullptr);
     866             : }
     867             : 
     868             : #endif  // V8_FAST_TLS_SUPPORTED
     869             : 
     870             : 
     871      176978 : Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
     872             : #ifdef V8_FAST_TLS_SUPPORTED
     873             :   bool check_fast_tls = false;
     874             :   if (tls_base_offset_initialized == 0) {
     875             :     check_fast_tls = true;
     876             :     InitializeTlsBaseOffset();
     877             :   }
     878             : #endif
     879             :   pthread_key_t key;
     880      176978 :   int result = pthread_key_create(&key, nullptr);
     881             :   DCHECK_EQ(0, result);
     882             :   USE(result);
     883      176978 :   LocalStorageKey local_key = PthreadKeyToLocalKey(key);
     884             : #ifdef V8_FAST_TLS_SUPPORTED
     885             :   // If we just initialized fast TLS support, make sure it works.
     886             :   if (check_fast_tls) CheckFastTls(local_key);
     887             : #endif
     888      176978 :   return local_key;
     889             : }
     890             : 
     891             : 
     892          32 : void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
     893             :   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
     894          32 :   int result = pthread_key_delete(pthread_key);
     895             :   DCHECK_EQ(0, result);
     896             :   USE(result);
     897          32 : }
     898             : 
     899             : 
     900     1928297 : void* Thread::GetThreadLocal(LocalStorageKey key) {
     901             :   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
     902     1928297 :   return pthread_getspecific(pthread_key);
     903             : }
     904             : 
     905             : 
     906     1281450 : void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
     907             :   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
     908     1281450 :   int result = pthread_setspecific(pthread_key, value);
     909             :   DCHECK_EQ(0, result);
     910             :   USE(result);
     911     1281462 : }
     912             : 
     913             : #undef LOG_TAG
     914             : #undef MAP_ANONYMOUS
     915             : #undef MADV_FREE
     916             : 
     917             : }  // namespace base
     918             : }  // namespace v8

Generated by: LCOV version 1.10