LCOV - code coverage report
Current view: top level - src/base/platform - platform.h (source / functions) Hit Total Coverage
Test: app.info Lines: 19 21 90.5 %
Date: 2019-04-18 Functions: 2 2 100.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             : // This module contains the platform-specific code. This make the rest of the
       6             : // code less dependent on operating system, compilers and runtime libraries.
       7             : // This module does specifically not deal with differences between different
       8             : // processor architecture.
       9             : // The platform classes have the same definition for all platforms. The
      10             : // implementation for a particular platform is put in platform_<os>.cc.
      11             : // The build system then uses the implementation for the target platform.
      12             : //
      13             : // This design has been chosen because it is simple and fast. Alternatively,
      14             : // the platform dependent classes could have been implemented using abstract
      15             : // superclasses with virtual methods and having specializations for each
      16             : // platform. This design was rejected because it was more complicated and
      17             : // slower. It would require factory methods for selecting the right
      18             : // implementation and the overhead of virtual methods for performance
      19             : // sensitive like mutex locking/unlocking.
      20             : 
      21             : #ifndef V8_BASE_PLATFORM_PLATFORM_H_
      22             : #define V8_BASE_PLATFORM_PLATFORM_H_
      23             : 
      24             : #include <cstdarg>
      25             : #include <string>
      26             : #include <vector>
      27             : 
      28             : #include "src/base/base-export.h"
      29             : #include "src/base/build_config.h"
      30             : #include "src/base/compiler-specific.h"
      31             : #include "src/base/platform/mutex.h"
      32             : #include "src/base/platform/semaphore.h"
      33             : 
      34             : #if V8_OS_QNX
      35             : #include "src/base/qnx-math.h"
      36             : #endif
      37             : 
      38             : namespace v8 {
      39             : 
      40             : namespace base {
      41             : 
      42             : // ----------------------------------------------------------------------------
      43             : // Fast TLS support
      44             : 
      45             : #ifndef V8_NO_FAST_TLS
      46             : 
      47             : #if V8_CC_MSVC && V8_HOST_ARCH_IA32
      48             : 
      49             : #define V8_FAST_TLS_SUPPORTED 1
      50             : 
      51             : V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index);
      52             : 
      53             : inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
      54             :   const intptr_t kTibInlineTlsOffset = 0xE10;
      55             :   const intptr_t kTibExtraTlsOffset = 0xF94;
      56             :   const intptr_t kMaxInlineSlots = 64;
      57             :   const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
      58             :   const intptr_t kSystemPointerSize = sizeof(void*);
      59             :   DCHECK(0 <= index && index < kMaxSlots);
      60             :   USE(kMaxSlots);
      61             :   if (index < kMaxInlineSlots) {
      62             :     return static_cast<intptr_t>(
      63             :         __readfsdword(kTibInlineTlsOffset + kSystemPointerSize * index));
      64             :   }
      65             :   intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
      66             :   DCHECK_NE(extra, 0);
      67             :   return *reinterpret_cast<intptr_t*>(extra + kSystemPointerSize *
      68             :                                                   (index - kMaxInlineSlots));
      69             : }
      70             : 
      71             : #elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
      72             : 
      73             : #define V8_FAST_TLS_SUPPORTED 1
      74             : 
      75             : extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset;
      76             : 
      77             : V8_INLINE intptr_t InternalGetExistingThreadLocal(intptr_t index);
      78             : 
      79             : inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
      80             :   intptr_t result;
      81             : #if V8_HOST_ARCH_IA32
      82             :   asm("movl %%gs:(%1,%2,4), %0;"
      83             :       :"=r"(result)  // Output must be a writable register.
      84             :       :"r"(kMacTlsBaseOffset), "r"(index));
      85             : #else
      86             :   asm("movq %%gs:(%1,%2,8), %0;"
      87             :       :"=r"(result)
      88             :       :"r"(kMacTlsBaseOffset), "r"(index));
      89             : #endif
      90             :   return result;
      91             : }
      92             : 
      93             : #endif
      94             : 
      95             : #endif  // V8_NO_FAST_TLS
      96             : 
      97             : class PageAllocator;
      98             : class TimezoneCache;
      99             : 
     100             : // ----------------------------------------------------------------------------
     101             : // OS
     102             : //
     103             : // This class has static methods for the different platform specific
     104             : // functions. Add methods here to cope with differences between the
     105             : // supported platforms.
     106             : 
     107             : class V8_BASE_EXPORT OS {
     108             :  public:
     109             :   // Initialize the OS class.
     110             :   // - hard_abort: If true, OS::Abort() will crash instead of aborting.
     111             :   // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
     112             :   static void Initialize(bool hard_abort, const char* const gc_fake_mmap);
     113             : 
     114             :   // Returns the accumulated user time for thread. This routine
     115             :   // can be used for profiling. The implementation should
     116             :   // strive for high-precision timer resolution, preferable
     117             :   // micro-second resolution.
     118             :   static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
     119             : 
     120             :   // Returns current time as the number of milliseconds since
     121             :   // 00:00:00 UTC, January 1, 1970.
     122             :   static double TimeCurrentMillis();
     123             : 
     124             :   static TimezoneCache* CreateTimezoneCache();
     125             : 
     126             :   // Returns last OS error.
     127             :   static int GetLastError();
     128             : 
     129             :   static FILE* FOpen(const char* path, const char* mode);
     130             :   static bool Remove(const char* path);
     131             : 
     132             :   static char DirectorySeparator();
     133             :   static bool isDirectorySeparator(const char ch);
     134             : 
     135             :   // Opens a temporary file, the file is auto removed on close.
     136             :   static FILE* OpenTemporaryFile();
     137             : 
     138             :   // Log file open mode is platform-dependent due to line ends issues.
     139             :   static const char* const LogFileOpenMode;
     140             : 
     141             :   // Print output to console. This is mostly used for debugging output.
     142             :   // On platforms that has standard terminal output, the output
     143             :   // should go to stdout.
     144             :   static PRINTF_FORMAT(1, 2) void Print(const char* format, ...);
     145             :   static PRINTF_FORMAT(1, 0) void VPrint(const char* format, va_list args);
     146             : 
     147             :   // Print output to a file. This is mostly used for debugging output.
     148             :   static PRINTF_FORMAT(2, 3) void FPrint(FILE* out, const char* format, ...);
     149             :   static PRINTF_FORMAT(2, 0) void VFPrint(FILE* out, const char* format,
     150             :                                           va_list args);
     151             : 
     152             :   // Print error output to console. This is mostly used for error message
     153             :   // output. On platforms that has standard terminal output, the output
     154             :   // should go to stderr.
     155             :   static PRINTF_FORMAT(1, 2) void PrintError(const char* format, ...);
     156             :   static PRINTF_FORMAT(1, 0) void VPrintError(const char* format, va_list args);
     157             : 
     158             :   // Memory permissions. These should be kept in sync with the ones in
     159             :   // v8::PageAllocator.
     160             :   enum class MemoryPermission {
     161             :     kNoAccess,
     162             :     kRead,
     163             :     kReadWrite,
     164             :     // TODO(hpayer): Remove this flag. Memory should never be rwx.
     165             :     kReadWriteExecute,
     166             :     kReadExecute
     167             :   };
     168             : 
     169             :   static bool HasLazyCommits();
     170             : 
     171             :   // Sleep for a specified time interval.
     172             :   static void Sleep(TimeDelta interval);
     173             : 
     174             :   // Abort the current process.
     175             :   [[noreturn]] static void Abort();
     176             : 
     177             :   // Debug break.
     178             :   static void DebugBreak();
     179             : 
     180             :   // Walk the stack.
     181             :   static const int kStackWalkError = -1;
     182             :   static const int kStackWalkMaxNameLen = 256;
     183             :   static const int kStackWalkMaxTextLen = 256;
     184             :   struct StackFrame {
     185             :     void* address;
     186             :     char text[kStackWalkMaxTextLen];
     187             :   };
     188             : 
     189      116216 :   class V8_BASE_EXPORT MemoryMappedFile {
     190             :    public:
     191             :     enum class FileMode { kReadOnly, kReadWrite };
     192             : 
     193      116216 :     virtual ~MemoryMappedFile() = default;
     194             :     virtual void* memory() const = 0;
     195             :     virtual size_t size() const = 0;
     196             : 
     197             :     static MemoryMappedFile* open(const char* name,
     198             :                                   FileMode mode = FileMode::kReadWrite);
     199             :     static MemoryMappedFile* create(const char* name, size_t size,
     200             :                                     void* initial);
     201             :   };
     202             : 
     203             :   // Safe formatting print. Ensures that str is always null-terminated.
     204             :   // Returns the number of chars written, or -1 if output was truncated.
     205             :   static PRINTF_FORMAT(3, 4) int SNPrintF(char* str, int length,
     206             :                                           const char* format, ...);
     207             :   static PRINTF_FORMAT(3, 0) int VSNPrintF(char* str, int length,
     208             :                                            const char* format, va_list args);
     209             : 
     210             :   static char* StrChr(char* str, int c);
     211             :   static void StrNCpy(char* dest, int length, const char* src, size_t n);
     212             : 
     213             :   // Support for the profiler.  Can do nothing, in which case ticks
     214             :   // occurring in shared libraries will not be properly accounted for.
     215           0 :   struct SharedLibraryAddress {
     216             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     217             :                          uintptr_t end)
     218           0 :         : library_path(library_path), start(start), end(end), aslr_slide(0) {}
     219             :     SharedLibraryAddress(const std::string& library_path, uintptr_t start,
     220             :                          uintptr_t end, intptr_t aslr_slide)
     221             :         : library_path(library_path),
     222             :           start(start),
     223             :           end(end),
     224             :           aslr_slide(aslr_slide) {}
     225             : 
     226             :     std::string library_path;
     227             :     uintptr_t start;
     228             :     uintptr_t end;
     229             :     intptr_t aslr_slide;
     230             :   };
     231             : 
     232             :   static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
     233             : 
     234             :   // Support for the profiler.  Notifies the external profiling
     235             :   // process that a code moving garbage collection starts.  Can do
     236             :   // nothing, in which case the code objects must not move (e.g., by
     237             :   // using --never-compact) if accurate profiling is desired.
     238             :   static void SignalCodeMovingGC();
     239             : 
     240             :   // Support runtime detection of whether the hard float option of the
     241             :   // EABI is used.
     242             :   static bool ArmUsingHardFloat();
     243             : 
     244             :   // Returns the activation frame alignment constraint or zero if
     245             :   // the platform doesn't care. Guaranteed to be a power of two.
     246             :   static int ActivationFrameAlignment();
     247             : 
     248             :   static int GetCurrentProcessId();
     249             : 
     250             :   static int GetCurrentThreadId();
     251             : 
     252             :   static void ExitProcess(int exit_code);
     253             : 
     254             :  private:
     255             :   // These classes use the private memory management API below.
     256             :   friend class MemoryMappedFile;
     257             :   friend class PosixMemoryMappedFile;
     258             :   friend class v8::base::PageAllocator;
     259             : 
     260             :   static size_t AllocatePageSize();
     261             : 
     262             :   static size_t CommitPageSize();
     263             : 
     264             :   static void SetRandomMmapSeed(int64_t seed);
     265             : 
     266             :   static void* GetRandomMmapAddr();
     267             : 
     268             :   V8_WARN_UNUSED_RESULT static void* Allocate(void* address, size_t size,
     269             :                                               size_t alignment,
     270             :                                               MemoryPermission access);
     271             : 
     272             :   V8_WARN_UNUSED_RESULT static bool Free(void* address, const size_t size);
     273             : 
     274             :   V8_WARN_UNUSED_RESULT static bool Release(void* address, size_t size);
     275             : 
     276             :   V8_WARN_UNUSED_RESULT static bool SetPermissions(void* address, size_t size,
     277             :                                                    MemoryPermission access);
     278             : 
     279             :   V8_WARN_UNUSED_RESULT static bool DiscardSystemPages(void* address,
     280             :                                                        size_t size);
     281             : 
     282             :   static const int msPerSecond = 1000;
     283             : 
     284             : #if V8_OS_POSIX
     285             :   static const char* GetGCFakeMMapFile();
     286             : #endif
     287             : 
     288             :   DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
     289             : };
     290             : 
     291             : #if (defined(_WIN32) || defined(_WIN64))
     292             : V8_BASE_EXPORT void EnsureConsoleOutputWin32();
     293             : #endif  // (defined(_WIN32) || defined(_WIN64))
     294             : 
     295             : inline void EnsureConsoleOutput() {
     296             : #if (defined(_WIN32) || defined(_WIN64))
     297             :   // Windows requires extra calls to send assert output to the console
     298             :   // rather than a dialog box.
     299             :   EnsureConsoleOutputWin32();
     300             : #endif  // (defined(_WIN32) || defined(_WIN64))
     301             : }
     302             : 
     303             : // ----------------------------------------------------------------------------
     304             : // Thread
     305             : //
     306             : // Thread objects are used for creating and running threads. When the start()
     307             : // method is called the new thread starts running the run() method in the new
     308             : // thread. The Thread object should not be deallocated before the thread has
     309             : // terminated.
     310             : 
     311             : class V8_BASE_EXPORT Thread {
     312             :  public:
     313             :   // Opaque data type for thread-local storage keys.
     314             :   using LocalStorageKey = int32_t;
     315             : 
     316             :   class Options {
     317             :    public:
     318             :     Options() : name_("v8:<unknown>"), stack_size_(0) {}
     319             :     explicit Options(const char* name, int stack_size = 0)
     320      501179 :         : name_(name), stack_size_(stack_size) {}
     321             : 
     322             :     const char* name() const { return name_; }
     323             :     int stack_size() const { return stack_size_; }
     324             : 
     325             :    private:
     326             :     const char* name_;
     327             :     int stack_size_;
     328             :   };
     329             : 
     330             :   // Create new thread.
     331             :   explicit Thread(const Options& options);
     332             :   virtual ~Thread();
     333             : 
     334             :   // Start new thread by calling the Run() method on the new thread.
     335             :   void Start();
     336             : 
     337             :   // Start new thread and wait until Run() method is called on the new thread.
     338         783 :   void StartSynchronously() {
     339         783 :     start_semaphore_ = new Semaphore(0);
     340         783 :     Start();
     341         783 :     start_semaphore_->Wait();
     342         783 :     delete start_semaphore_;
     343         783 :     start_semaphore_ = nullptr;
     344         783 :   }
     345             : 
     346             :   // Wait until thread terminates.
     347             :   void Join();
     348             : 
     349             :   inline const char* name() const {
     350      453807 :     return name_;
     351             :   }
     352             : 
     353             :   // Abstract method for run handler.
     354             :   virtual void Run() = 0;
     355             : 
     356             :   // Thread-local storage.
     357             :   static LocalStorageKey CreateThreadLocalKey();
     358             :   static void DeleteThreadLocalKey(LocalStorageKey key);
     359             :   static void* GetThreadLocal(LocalStorageKey key);
     360             :   static int GetThreadLocalInt(LocalStorageKey key) {
     361      685686 :     return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
     362             :   }
     363             :   static void SetThreadLocal(LocalStorageKey key, void* value);
     364             :   static void SetThreadLocalInt(LocalStorageKey key, int value) {
     365       67266 :     SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
     366             :   }
     367             :   static bool HasThreadLocal(LocalStorageKey key) {
     368         192 :     return GetThreadLocal(key) != nullptr;
     369             :   }
     370             : 
     371             : #ifdef V8_FAST_TLS_SUPPORTED
     372             :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     373             :     void* result = reinterpret_cast<void*>(
     374             :         InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
     375             :     DCHECK(result == GetThreadLocal(key));
     376             :     return result;
     377             :   }
     378             : #else
     379             :   static inline void* GetExistingThreadLocal(LocalStorageKey key) {
     380      921216 :     return GetThreadLocal(key);
     381             :   }
     382             : #endif
     383             : 
     384             :   // The thread name length is limited to 16 based on Linux's implementation of
     385             :   // prctl().
     386             :   static const int kMaxThreadNameLength = 16;
     387             : 
     388             :   class PlatformData;
     389             :   PlatformData* data() { return data_; }
     390             : 
     391      453158 :   void NotifyStartedAndRun() {
     392      453158 :     if (start_semaphore_) start_semaphore_->Signal();
     393      453158 :     Run();
     394      432535 :   }
     395             : 
     396             :  private:
     397             :   void set_name(const char* name);
     398             : 
     399             :   PlatformData* data_;
     400             : 
     401             :   char name_[kMaxThreadNameLength];
     402             :   int stack_size_;
     403             :   Semaphore* start_semaphore_;
     404             : 
     405             :   DISALLOW_COPY_AND_ASSIGN(Thread);
     406             : };
     407             : 
     408             : }  // namespace base
     409             : }  // namespace v8
     410             : 
     411             : #endif  // V8_BASE_PLATFORM_PLATFORM_H_

Generated by: LCOV version 1.10