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

Generated by: LCOV version 1.10