Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // Platform specific code for Linux goes here. For the POSIX comaptible parts
     29 // the implementation is in platform-posix.cc.
     30 
     31 #include <pthread.h>
     32 #include <semaphore.h>
     33 #include <signal.h>
     34 #include <sys/prctl.h>
     35 #include <sys/time.h>
     36 #include <sys/resource.h>
     37 #include <sys/syscall.h>
     38 #include <sys/types.h>
     39 #include <stdlib.h>
     40 
     41 // Ubuntu Dapper requires memory pages to be marked as
     42 // executable. Otherwise, OS raises an exception when executing code
     43 // in that page.
     44 #include <sys/types.h>  // mmap & munmap
     45 #include <sys/mman.h>   // mmap & munmap
     46 #include <sys/stat.h>   // open
     47 #include <fcntl.h>      // open
     48 #include <unistd.h>     // sysconf
     49 #ifdef __GLIBC__
     50 #include <execinfo.h>   // backtrace, backtrace_symbols
     51 #endif  // def __GLIBC__
     52 #include <strings.h>    // index
     53 #include <errno.h>
     54 #include <stdarg.h>
     55 
     56 #undef MAP_TYPE
     57 
     58 #include "v8.h"
     59 
     60 #include "platform-posix.h"
     61 #include "platform.h"
     62 #include "v8threads.h"
     63 #include "vm-state-inl.h"
     64 
     65 
     66 namespace v8 {
     67 namespace internal {
     68 
     69 // 0 is never a valid thread id on Linux since tids and pids share a
     70 // name space and pid 0 is reserved (see man 2 kill).
     71 static const pthread_t kNoThread = (pthread_t) 0;
     72 
     73 
     74 double ceiling(double x) {
     75   return ceil(x);
     76 }
     77 
     78 
     79 static Mutex* limit_mutex = NULL;
     80 
     81 
     82 void OS::SetUp() {
     83   // Seed the random number generator. We preserve microsecond resolution.
     84   uint64_t seed = Ticks() ^ (getpid() << 16);
     85   srandom(static_cast<unsigned int>(seed));
     86   limit_mutex = CreateMutex();
     87 
     88 #ifdef __arm__
     89   // When running on ARM hardware check that the EABI used by V8 and
     90   // by the C code is the same.
     91   bool hard_float = OS::ArmUsingHardFloat();
     92   if (hard_float) {
     93 #if !USE_EABI_HARDFLOAT
     94     PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without "
     95            "-DUSE_EABI_HARDFLOAT\n");
     96     exit(1);
     97 #endif
     98   } else {
     99 #if USE_EABI_HARDFLOAT
    100     PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with "
    101            "-DUSE_EABI_HARDFLOAT\n");
    102     exit(1);
    103 #endif
    104   }
    105 #endif
    106 }
    107 
    108 
    109 void OS::PostSetUp() {
    110   // Math functions depend on CPU features therefore they are initialized after
    111   // CPU.
    112   MathSetup();
    113 }
    114 
    115 
    116 uint64_t OS::CpuFeaturesImpliedByPlatform() {
    117   return 0;  // Linux runs on anything.
    118 }
    119 
    120 
    121 #ifdef __arm__
    122 static bool CPUInfoContainsString(const char * search_string) {
    123   const char* file_name = "/proc/cpuinfo";
    124   // This is written as a straight shot one pass parser
    125   // and not using STL string and ifstream because,
    126   // on Linux, it's reading from a (non-mmap-able)
    127   // character special device.
    128   FILE* f = NULL;
    129   const char* what = search_string;
    130 
    131   if (NULL == (f = fopen(file_name, "r")))
    132     return false;
    133 
    134   int k;
    135   while (EOF != (k = fgetc(f))) {
    136     if (k == *what) {
    137       ++what;
    138       while ((*what != '\0') && (*what == fgetc(f))) {
    139         ++what;
    140       }
    141       if (*what == '\0') {
    142         fclose(f);
    143         return true;
    144       } else {
    145         what = search_string;
    146       }
    147     }
    148   }
    149   fclose(f);
    150 
    151   // Did not find string in the proc file.
    152   return false;
    153 }
    154 
    155 
    156 bool OS::ArmCpuHasFeature(CpuFeature feature) {
    157   const char* search_string = NULL;
    158   // Simple detection of VFP at runtime for Linux.
    159   // It is based on /proc/cpuinfo, which reveals hardware configuration
    160   // to user-space applications.  According to ARM (mid 2009), no similar
    161   // facility is universally available on the ARM architectures,
    162   // so it's up to individual OSes to provide such.
    163   switch (feature) {
    164     case VFP3:
    165       search_string = "vfpv3";
    166       break;
    167     case ARMv7:
    168       search_string = "ARMv7";
    169       break;
    170     default:
    171       UNREACHABLE();
    172   }
    173 
    174   if (CPUInfoContainsString(search_string)) {
    175     return true;
    176   }
    177 
    178   if (feature == VFP3) {
    179     // Some old kernels will report vfp not vfpv3. Here we make a last attempt
    180     // to detect vfpv3 by checking for vfp *and* neon, since neon is only
    181     // available on architectures with vfpv3.
    182     // Checking neon on its own is not enough as it is possible to have neon
    183     // without vfp.
    184     if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) {
    185       return true;
    186     }
    187   }
    188 
    189   return false;
    190 }
    191 
    192 
    193 // Simple helper function to detect whether the C code is compiled with
    194 // option -mfloat-abi=hard. The register d0 is loaded with 1.0 and the register
    195 // pair r0, r1 is loaded with 0.0. If -mfloat-abi=hard is pased to GCC then
    196 // calling this will return 1.0 and otherwise 0.0.
    197 static void ArmUsingHardFloatHelper() {
    198   asm("mov r0, #0":::"r0");
    199 #if defined(__VFP_FP__) && !defined(__SOFTFP__)
    200   // Load 0x3ff00000 into r1 using instructions available in both ARM
    201   // and Thumb mode.
    202   asm("mov r1, #3":::"r1");
    203   asm("mov r2, #255":::"r2");
    204   asm("lsl r1, r1, #8":::"r1");
    205   asm("orr r1, r1, r2":::"r1");
    206   asm("lsl r1, r1, #20":::"r1");
    207   // For vmov d0, r0, r1 use ARM mode.
    208 #ifdef __thumb__
    209   asm volatile(
    210     "@   Enter ARM Mode  \n\t"
    211     "    adr r3, 1f      \n\t"
    212     "    bx  r3          \n\t"
    213     "    .ALIGN 4        \n\t"
    214     "    .ARM            \n"
    215     "1:  vmov d0, r0, r1 \n\t"
    216     "@   Enter THUMB Mode\n\t"
    217     "    adr r3, 2f+1    \n\t"
    218     "    bx  r3          \n\t"
    219     "    .THUMB          \n"
    220     "2:                  \n\t":::"r3");
    221 #else
    222   asm("vmov d0, r0, r1");
    223 #endif  // __thumb__
    224 #endif  // defined(__VFP_FP__) && !defined(__SOFTFP__)
    225   asm("mov r1, #0":::"r1");
    226 }
    227 
    228 
    229 bool OS::ArmUsingHardFloat() {
    230   // Cast helper function from returning void to returning double.
    231   typedef double (*F)();
    232   F f = FUNCTION_CAST<F>(FUNCTION_ADDR(ArmUsingHardFloatHelper));
    233   return f() == 1.0;
    234 }
    235 #endif  // def __arm__
    236 
    237 
    238 #ifdef __mips__
    239 bool OS::MipsCpuHasFeature(CpuFeature feature) {
    240   const char* search_string = NULL;
    241   const char* file_name = "/proc/cpuinfo";
    242   // Simple detection of FPU at runtime for Linux.
    243   // It is based on /proc/cpuinfo, which reveals hardware configuration
    244   // to user-space applications.  According to MIPS (early 2010), no similar
    245   // facility is universally available on the MIPS architectures,
    246   // so it's up to individual OSes to provide such.
    247   //
    248   // This is written as a straight shot one pass parser
    249   // and not using STL string and ifstream because,
    250   // on Linux, it's reading from a (non-mmap-able)
    251   // character special device.
    252 
    253   switch (feature) {
    254     case FPU:
    255       search_string = "FPU";
    256       break;
    257     default:
    258       UNREACHABLE();
    259   }
    260 
    261   FILE* f = NULL;
    262   const char* what = search_string;
    263 
    264   if (NULL == (f = fopen(file_name, "r")))
    265     return false;
    266 
    267   int k;
    268   while (EOF != (k = fgetc(f))) {
    269     if (k == *what) {
    270       ++what;
    271       while ((*what != '\0') && (*what == fgetc(f))) {
    272         ++what;
    273       }
    274       if (*what == '\0') {
    275         fclose(f);
    276         return true;
    277       } else {
    278         what = search_string;
    279       }
    280     }
    281   }
    282   fclose(f);
    283 
    284   // Did not find string in the proc file.
    285   return false;
    286 }
    287 #endif  // def __mips__
    288 
    289 
    290 int OS::ActivationFrameAlignment() {
    291 #ifdef V8_TARGET_ARCH_ARM
    292   // On EABI ARM targets this is required for fp correctness in the
    293   // runtime system.
    294   return 8;
    295 #elif V8_TARGET_ARCH_MIPS
    296   return 8;
    297 #endif
    298   // With gcc 4.4 the tree vectorization optimizer can generate code
    299   // that requires 16 byte alignment such as movdqa on x86.
    300   return 16;
    301 }
    302 
    303 
    304 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
    305 #if (defined(V8_TARGET_ARCH_ARM) && defined(__arm__)) || \
    306     (defined(V8_TARGET_ARCH_MIPS) && defined(__mips__))
    307   // Only use on ARM or MIPS hardware.
    308   MemoryBarrier();
    309 #else
    310   __asm__ __volatile__("" : : : "memory");
    311   // An x86 store acts as a release barrier.
    312 #endif
    313   *ptr = value;
    314 }
    315 
    316 
    317 const char* OS::LocalTimezone(double time) {
    318   if (isnan(time)) return "";
    319   time_t tv = static_cast<time_t>(floor(time/msPerSecond));
    320   struct tm* t = localtime(&tv);
    321   if (NULL == t) return "";
    322   return t->tm_zone;
    323 }
    324 
    325 
    326 double OS::LocalTimeOffset() {
    327   time_t tv = time(NULL);
    328   struct tm* t = localtime(&tv);
    329   // tm_gmtoff includes any daylight savings offset, so subtract it.
    330   return static_cast<double>(t->tm_gmtoff * msPerSecond -
    331                              (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
    332 }
    333 
    334 
    335 // We keep the lowest and highest addresses mapped as a quick way of
    336 // determining that pointers are outside the heap (used mostly in assertions
    337 // and verification).  The estimate is conservative, i.e., not all addresses in
    338 // 'allocated' space are actually allocated to our heap.  The range is
    339 // [lowest, highest), inclusive on the low and and exclusive on the high end.
    340 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
    341 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
    342 
    343 
    344 static void UpdateAllocatedSpaceLimits(void* address, int size) {
    345   ASSERT(limit_mutex != NULL);
    346   ScopedLock lock(limit_mutex);
    347 
    348   lowest_ever_allocated = Min(lowest_ever_allocated, address);
    349   highest_ever_allocated =
    350       Max(highest_ever_allocated,
    351           reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
    352 }
    353 
    354 
    355 bool OS::IsOutsideAllocatedSpace(void* address) {
    356   return address < lowest_ever_allocated || address >= highest_ever_allocated;
    357 }
    358 
    359 
    360 size_t OS::AllocateAlignment() {
    361   return sysconf(_SC_PAGESIZE);
    362 }
    363 
    364 
    365 void* OS::Allocate(const size_t requested,
    366                    size_t* allocated,
    367                    bool is_executable) {
    368   const size_t msize = RoundUp(requested, AllocateAlignment());
    369   int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
    370   void* addr = OS::GetRandomMmapAddr();
    371   void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    372   if (mbase == MAP_FAILED) {
    373     LOG(i::Isolate::Current(),
    374         StringEvent("OS::Allocate", "mmap failed"));
    375     return NULL;
    376   }
    377   *allocated = msize;
    378   UpdateAllocatedSpaceLimits(mbase, msize);
    379   return mbase;
    380 }
    381 
    382 
    383 void OS::Free(void* address, const size_t size) {
    384   // TODO(1240712): munmap has a return value which is ignored here.
    385   int result = munmap(address, size);
    386   USE(result);
    387   ASSERT(result == 0);
    388 }
    389 
    390 
    391 void OS::Sleep(int milliseconds) {
    392   unsigned int ms = static_cast<unsigned int>(milliseconds);
    393   usleep(1000 * ms);
    394 }
    395 
    396 
    397 void OS::Abort() {
    398   // Redirect to std abort to signal abnormal program termination.
    399   if (FLAG_break_on_abort) {
    400     DebugBreak();
    401   }
    402   abort();
    403 }
    404 
    405 
    406 void OS::DebugBreak() {
    407 // TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
    408 //  which is the architecture of generated code).
    409 #if (defined(__arm__) || defined(__thumb__))
    410 # if defined(CAN_USE_ARMV5_INSTRUCTIONS)
    411   asm("bkpt 0");
    412 # endif
    413 #elif defined(__mips__)
    414   asm("break");
    415 #else
    416   asm("int $3");
    417 #endif
    418 }
    419 
    420 
    421 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
    422  public:
    423   PosixMemoryMappedFile(FILE* file, void* memory, int size)
    424     : file_(file), memory_(memory), size_(size) { }
    425   virtual ~PosixMemoryMappedFile();
    426   virtual void* memory() { return memory_; }
    427   virtual int size() { return size_; }
    428  private:
    429   FILE* file_;
    430   void* memory_;
    431   int size_;
    432 };
    433 
    434 
    435 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
    436   FILE* file = fopen(name, "r+");
    437   if (file == NULL) return NULL;
    438 
    439   fseek(file, 0, SEEK_END);
    440   int size = ftell(file);
    441 
    442   void* memory =
    443       mmap(OS::GetRandomMmapAddr(),
    444            size,
    445            PROT_READ | PROT_WRITE,
    446            MAP_SHARED,
    447            fileno(file),
    448            0);
    449   return new PosixMemoryMappedFile(file, memory, size);
    450 }
    451 
    452 
    453 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
    454     void* initial) {
    455   FILE* file = fopen(name, "w+");
    456   if (file == NULL) return NULL;
    457   int result = fwrite(initial, size, 1, file);
    458   if (result < 1) {
    459     fclose(file);
    460     return NULL;
    461   }
    462   void* memory =
    463       mmap(OS::GetRandomMmapAddr(),
    464            size,
    465            PROT_READ | PROT_WRITE,
    466            MAP_SHARED,
    467            fileno(file),
    468            0);
    469   return new PosixMemoryMappedFile(file, memory, size);
    470 }
    471 
    472 
    473 PosixMemoryMappedFile::~PosixMemoryMappedFile() {
    474   if (memory_) OS::Free(memory_, size_);
    475   fclose(file_);
    476 }
    477 
    478 
    479 void OS::LogSharedLibraryAddresses() {
    480   // This function assumes that the layout of the file is as follows:
    481   // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
    482   // If we encounter an unexpected situation we abort scanning further entries.
    483   FILE* fp = fopen("/proc/self/maps", "r");
    484   if (fp == NULL) return;
    485 
    486   // Allocate enough room to be able to store a full file name.
    487   const int kLibNameLen = FILENAME_MAX + 1;
    488   char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
    489 
    490   i::Isolate* isolate = ISOLATE;
    491   // This loop will terminate once the scanning hits an EOF.
    492   while (true) {
    493     uintptr_t start, end;
    494     char attr_r, attr_w, attr_x, attr_p;
    495     // Parse the addresses and permission bits at the beginning of the line.
    496     if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
    497     if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
    498 
    499     int c;
    500     if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
    501       // Found a read-only executable entry. Skip characters until we reach
    502       // the beginning of the filename or the end of the line.
    503       do {
    504         c = getc(fp);
    505       } while ((c != EOF) && (c != '\n') && (c != '/'));
    506       if (c == EOF) break;  // EOF: Was unexpected, just exit.
    507 
    508       // Process the filename if found.
    509       if (c == '/') {
    510         ungetc(c, fp);  // Push the '/' back into the stream to be read below.
    511 
    512         // Read to the end of the line. Exit if the read fails.
    513         if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
    514 
    515         // Drop the newline character read by fgets. We do not need to check
    516         // for a zero-length string because we know that we at least read the
    517         // '/' character.
    518         lib_name[strlen(lib_name) - 1] = '\0';
    519       } else {
    520         // No library name found, just record the raw address range.
    521         snprintf(lib_name, kLibNameLen,
    522                  "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
    523       }
    524       LOG(isolate, SharedLibraryEvent(lib_name, start, end));
    525     } else {
    526       // Entry not describing executable data. Skip to end of line to set up
    527       // reading the next entry.
    528       do {
    529         c = getc(fp);
    530       } while ((c != EOF) && (c != '\n'));
    531       if (c == EOF) break;
    532     }
    533   }
    534   free(lib_name);
    535   fclose(fp);
    536 }
    537 
    538 
    539 static const char kGCFakeMmap[] = "/tmp/__v8_gc__";
    540 
    541 
    542 void OS::SignalCodeMovingGC() {
    543   // Support for ll_prof.py.
    544   //
    545   // The Linux profiler built into the kernel logs all mmap's with
    546   // PROT_EXEC so that analysis tools can properly attribute ticks. We
    547   // do a mmap with a name known by ll_prof.py and immediately munmap
    548   // it. This injects a GC marker into the stream of events generated
    549   // by the kernel and allows us to synchronize V8 code log and the
    550   // kernel log.
    551   int size = sysconf(_SC_PAGESIZE);
    552   FILE* f = fopen(kGCFakeMmap, "w+");
    553   void* addr = mmap(OS::GetRandomMmapAddr(),
    554                     size,
    555                     PROT_READ | PROT_EXEC,
    556                     MAP_PRIVATE,
    557                     fileno(f),
    558                     0);
    559   ASSERT(addr != MAP_FAILED);
    560   OS::Free(addr, size);
    561   fclose(f);
    562 }
    563 
    564 
    565 int OS::StackWalk(Vector<OS::StackFrame> frames) {
    566   // backtrace is a glibc extension.
    567 #ifdef __GLIBC__
    568   int frames_size = frames.length();
    569   ScopedVector<void*> addresses(frames_size);
    570 
    571   int frames_count = backtrace(addresses.start(), frames_size);
    572 
    573   char** symbols = backtrace_symbols(addresses.start(), frames_count);
    574   if (symbols == NULL) {
    575     return kStackWalkError;
    576   }
    577 
    578   for (int i = 0; i < frames_count; i++) {
    579     frames[i].address = addresses[i];
    580     // Format a text representation of the frame based on the information
    581     // available.
    582     SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
    583              "%s",
    584              symbols[i]);
    585     // Make sure line termination is in place.
    586     frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
    587   }
    588 
    589   free(symbols);
    590 
    591   return frames_count;
    592 #else  // ndef __GLIBC__
    593   return 0;
    594 #endif  // ndef __GLIBC__
    595 }
    596 
    597 
    598 // Constants used for mmap.
    599 static const int kMmapFd = -1;
    600 static const int kMmapFdOffset = 0;
    601 
    602 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
    603 
    604 VirtualMemory::VirtualMemory(size_t size) {
    605   address_ = ReserveRegion(size);
    606   size_ = size;
    607 }
    608 
    609 
    610 VirtualMemory::VirtualMemory(size_t size, size_t alignment)
    611     : address_(NULL), size_(0) {
    612   ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
    613   size_t request_size = RoundUp(size + alignment,
    614                                 static_cast<intptr_t>(OS::AllocateAlignment()));
    615   void* reservation = mmap(OS::GetRandomMmapAddr(),
    616                            request_size,
    617                            PROT_NONE,
    618                            MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
    619                            kMmapFd,
    620                            kMmapFdOffset);
    621   if (reservation == MAP_FAILED) return;
    622 
    623   Address base = static_cast<Address>(reservation);
    624   Address aligned_base = RoundUp(base, alignment);
    625   ASSERT_LE(base, aligned_base);
    626 
    627   // Unmap extra memory reserved before and after the desired block.
    628   if (aligned_base != base) {
    629     size_t prefix_size = static_cast<size_t>(aligned_base - base);
    630     OS::Free(base, prefix_size);
    631     request_size -= prefix_size;
    632   }
    633 
    634   size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
    635   ASSERT_LE(aligned_size, request_size);
    636 
    637   if (aligned_size != request_size) {
    638     size_t suffix_size = request_size - aligned_size;
    639     OS::Free(aligned_base + aligned_size, suffix_size);
    640     request_size -= suffix_size;
    641   }
    642 
    643   ASSERT(aligned_size == request_size);
    644 
    645   address_ = static_cast<void*>(aligned_base);
    646   size_ = aligned_size;
    647 }
    648 
    649 
    650 VirtualMemory::~VirtualMemory() {
    651   if (IsReserved()) {
    652     bool result = ReleaseRegion(address(), size());
    653     ASSERT(result);
    654     USE(result);
    655   }
    656 }
    657 
    658 
    659 bool VirtualMemory::IsReserved() {
    660   return address_ != NULL;
    661 }
    662 
    663 
    664 void VirtualMemory::Reset() {
    665   address_ = NULL;
    666   size_ = 0;
    667 }
    668 
    669 
    670 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
    671   return CommitRegion(address, size, is_executable);
    672 }
    673 
    674 
    675 bool VirtualMemory::Uncommit(void* address, size_t size) {
    676   return UncommitRegion(address, size);
    677 }
    678 
    679 
    680 bool VirtualMemory::Guard(void* address) {
    681   OS::Guard(address, OS::CommitPageSize());
    682   return true;
    683 }
    684 
    685 
    686 void* VirtualMemory::ReserveRegion(size_t size) {
    687   void* result = mmap(OS::GetRandomMmapAddr(),
    688                       size,
    689                       PROT_NONE,
    690                       MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
    691                       kMmapFd,
    692                       kMmapFdOffset);
    693 
    694   if (result == MAP_FAILED) return NULL;
    695 
    696   return result;
    697 }
    698 
    699 
    700 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
    701   int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
    702   if (MAP_FAILED == mmap(base,
    703                          size,
    704                          prot,
    705                          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
    706                          kMmapFd,
    707                          kMmapFdOffset)) {
    708     return false;
    709   }
    710 
    711   UpdateAllocatedSpaceLimits(base, size);
    712   return true;
    713 }
    714 
    715 
    716 bool VirtualMemory::UncommitRegion(void* base, size_t size) {
    717   return mmap(base,
    718               size,
    719               PROT_NONE,
    720               MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
    721               kMmapFd,
    722               kMmapFdOffset) != MAP_FAILED;
    723 }
    724 
    725 
    726 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
    727   return munmap(base, size) == 0;
    728 }
    729 
    730 
    731 class Thread::PlatformData : public Malloced {
    732  public:
    733   PlatformData() : thread_(kNoThread) {}
    734 
    735   pthread_t thread_;  // Thread handle for pthread.
    736 };
    737 
    738 Thread::Thread(const Options& options)
    739     : data_(new PlatformData()),
    740       stack_size_(options.stack_size()) {
    741   set_name(options.name());
    742 }
    743 
    744 
    745 Thread::~Thread() {
    746   delete data_;
    747 }
    748 
    749 
    750 static void* ThreadEntry(void* arg) {
    751   Thread* thread = reinterpret_cast<Thread*>(arg);
    752   // This is also initialized by the first argument to pthread_create() but we
    753   // don't know which thread will run first (the original thread or the new
    754   // one) so we initialize it here too.
    755 #ifdef PR_SET_NAME
    756   prctl(PR_SET_NAME,
    757         reinterpret_cast<unsigned long>(thread->name()),  // NOLINT
    758         0, 0, 0);
    759 #endif
    760   thread->data()->thread_ = pthread_self();
    761   ASSERT(thread->data()->thread_ != kNoThread);
    762   thread->Run();
    763   return NULL;
    764 }
    765 
    766 
    767 void Thread::set_name(const char* name) {
    768   strncpy(name_, name, sizeof(name_));
    769   name_[sizeof(name_) - 1] = '\0';
    770 }
    771 
    772 
    773 void Thread::Start() {
    774   pthread_attr_t* attr_ptr = NULL;
    775   pthread_attr_t attr;
    776   if (stack_size_ > 0) {
    777     pthread_attr_init(&attr);
    778     pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
    779     attr_ptr = &attr;
    780   }
    781   int result = pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
    782   CHECK_EQ(0, result);
    783   ASSERT(data_->thread_ != kNoThread);
    784 }
    785 
    786 
    787 void Thread::Join() {
    788   pthread_join(data_->thread_, NULL);
    789 }
    790 
    791 
    792 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
    793   pthread_key_t key;
    794   int result = pthread_key_create(&key, NULL);
    795   USE(result);
    796   ASSERT(result == 0);
    797   return static_cast<LocalStorageKey>(key);
    798 }
    799 
    800 
    801 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
    802   pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
    803   int result = pthread_key_delete(pthread_key);
    804   USE(result);
    805   ASSERT(result == 0);
    806 }
    807 
    808 
    809 void* Thread::GetThreadLocal(LocalStorageKey key) {
    810   pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
    811   return pthread_getspecific(pthread_key);
    812 }
    813 
    814 
    815 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
    816   pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
    817   pthread_setspecific(pthread_key, value);
    818 }
    819 
    820 
    821 void Thread::YieldCPU() {
    822   sched_yield();
    823 }
    824 
    825 
    826 class LinuxMutex : public Mutex {
    827  public:
    828   LinuxMutex() {
    829     pthread_mutexattr_t attrs;
    830     int result = pthread_mutexattr_init(&attrs);
    831     ASSERT(result == 0);
    832     result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
    833     ASSERT(result == 0);
    834     result = pthread_mutex_init(&mutex_, &attrs);
    835     ASSERT(result == 0);
    836     USE(result);
    837   }
    838 
    839   virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); }
    840 
    841   virtual int Lock() {
    842     int result = pthread_mutex_lock(&mutex_);
    843     return result;
    844   }
    845 
    846   virtual int Unlock() {
    847     int result = pthread_mutex_unlock(&mutex_);
    848     return result;
    849   }
    850 
    851   virtual bool TryLock() {
    852     int result = pthread_mutex_trylock(&mutex_);
    853     // Return false if the lock is busy and locking failed.
    854     if (result == EBUSY) {
    855       return false;
    856     }
    857     ASSERT(result == 0);  // Verify no other errors.
    858     return true;
    859   }
    860 
    861  private:
    862   pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
    863 };
    864 
    865 
    866 Mutex* OS::CreateMutex() {
    867   return new LinuxMutex();
    868 }
    869 
    870 
    871 class LinuxSemaphore : public Semaphore {
    872  public:
    873   explicit LinuxSemaphore(int count) {  sem_init(&sem_, 0, count); }
    874   virtual ~LinuxSemaphore() { sem_destroy(&sem_); }
    875 
    876   virtual void Wait();
    877   virtual bool Wait(int timeout);
    878   virtual void Signal() { sem_post(&sem_); }
    879  private:
    880   sem_t sem_;
    881 };
    882 
    883 
    884 void LinuxSemaphore::Wait() {
    885   while (true) {
    886     int result = sem_wait(&sem_);
    887     if (result == 0) return;  // Successfully got semaphore.
    888     CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
    889   }
    890 }
    891 
    892 
    893 #ifndef TIMEVAL_TO_TIMESPEC
    894 #define TIMEVAL_TO_TIMESPEC(tv, ts) do {                            \
    895     (ts)->tv_sec = (tv)->tv_sec;                                    \
    896     (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
    897 } while (false)
    898 #endif
    899 
    900 
    901 bool LinuxSemaphore::Wait(int timeout) {
    902   const long kOneSecondMicros = 1000000;  // NOLINT
    903 
    904   // Split timeout into second and nanosecond parts.
    905   struct timeval delta;
    906   delta.tv_usec = timeout % kOneSecondMicros;
    907   delta.tv_sec = timeout / kOneSecondMicros;
    908 
    909   struct timeval current_time;
    910   // Get the current time.
    911   if (gettimeofday(&current_time, NULL) == -1) {
    912     return false;
    913   }
    914 
    915   // Calculate time for end of timeout.
    916   struct timeval end_time;
    917   timeradd(&current_time, &delta, &end_time);
    918 
    919   struct timespec ts;
    920   TIMEVAL_TO_TIMESPEC(&end_time, &ts);
    921   // Wait for semaphore signalled or timeout.
    922   while (true) {
    923     int result = sem_timedwait(&sem_, &ts);
    924     if (result == 0) return true;  // Successfully got semaphore.
    925     if (result > 0) {
    926       // For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1.
    927       errno = result;
    928       result = -1;
    929     }
    930     if (result == -1 && errno == ETIMEDOUT) return false;  // Timeout.
    931     CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
    932   }
    933 }
    934 
    935 
    936 Semaphore* OS::CreateSemaphore(int count) {
    937   return new LinuxSemaphore(count);
    938 }
    939 
    940 
    941 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
    942 // Android runs a fairly new Linux kernel, so signal info is there,
    943 // but the C library doesn't have the structs defined.
    944 
    945 struct sigcontext {
    946   uint32_t trap_no;
    947   uint32_t error_code;
    948   uint32_t oldmask;
    949   uint32_t gregs[16];
    950   uint32_t arm_cpsr;
    951   uint32_t fault_address;
    952 };
    953 typedef uint32_t __sigset_t;
    954 typedef struct sigcontext mcontext_t;
    955 typedef struct ucontext {
    956   uint32_t uc_flags;
    957   struct ucontext* uc_link;
    958   stack_t uc_stack;
    959   mcontext_t uc_mcontext;
    960   __sigset_t uc_sigmask;
    961 } ucontext_t;
    962 enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
    963 
    964 #elif !defined(__GLIBC__) && defined(__mips__)
    965 // MIPS version of sigcontext, for Android bionic.
    966 struct sigcontext {
    967   uint32_t regmask;
    968   uint32_t status;
    969   uint64_t pc;
    970   uint64_t gregs[32];
    971   uint64_t fpregs[32];
    972   uint32_t acx;
    973   uint32_t fpc_csr;
    974   uint32_t fpc_eir;
    975   uint32_t used_math;
    976   uint32_t dsp;
    977   uint64_t mdhi;
    978   uint64_t mdlo;
    979   uint32_t hi1;
    980   uint32_t lo1;
    981   uint32_t hi2;
    982   uint32_t lo2;
    983   uint32_t hi3;
    984   uint32_t lo3;
    985 };
    986 typedef uint32_t __sigset_t;
    987 typedef struct sigcontext mcontext_t;
    988 typedef struct ucontext {
    989   uint32_t uc_flags;
    990   struct ucontext* uc_link;
    991   stack_t uc_stack;
    992   mcontext_t uc_mcontext;
    993   __sigset_t uc_sigmask;
    994 } ucontext_t;
    995 
    996 #elif !defined(__GLIBC__) && defined(__i386__)
    997 // x86 version for Android.
    998 struct sigcontext {
    999   uint32_t gregs[19];
   1000   void* fpregs;
   1001   uint32_t oldmask;
   1002   uint32_t cr2;
   1003 };
   1004 
   1005 typedef uint32_t __sigset_t;
   1006 typedef struct sigcontext mcontext_t;
   1007 typedef struct ucontext {
   1008   uint32_t uc_flags;
   1009   struct ucontext* uc_link;
   1010   stack_t uc_stack;
   1011   mcontext_t uc_mcontext;
   1012   __sigset_t uc_sigmask;
   1013 } ucontext_t;
   1014 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
   1015 #endif
   1016 
   1017 
   1018 static int GetThreadID() {
   1019   // Glibc doesn't provide a wrapper for gettid(2).
   1020 #if defined(ANDROID)
   1021   return syscall(__NR_gettid);
   1022 #else
   1023   return syscall(SYS_gettid);
   1024 #endif
   1025 }
   1026 
   1027 
   1028 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   1029   USE(info);
   1030   if (signal != SIGPROF) return;
   1031   Isolate* isolate = Isolate::UncheckedCurrent();
   1032   if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
   1033     // We require a fully initialized and entered isolate.
   1034     return;
   1035   }
   1036   if (v8::Locker::IsActive() &&
   1037       !isolate->thread_manager()->IsLockedByCurrentThread()) {
   1038     return;
   1039   }
   1040 
   1041   Sampler* sampler = isolate->logger()->sampler();
   1042   if (sampler == NULL || !sampler->IsActive()) return;
   1043 
   1044   TickSample sample_obj;
   1045   TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
   1046   if (sample == NULL) sample = &sample_obj;
   1047 
   1048   // Extracting the sample from the context is extremely machine dependent.
   1049   ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
   1050   mcontext_t& mcontext = ucontext->uc_mcontext;
   1051   sample->state = isolate->current_vm_state();
   1052 #if V8_HOST_ARCH_IA32
   1053   sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
   1054   sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
   1055   sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
   1056 #elif V8_HOST_ARCH_X64
   1057   sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
   1058   sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
   1059   sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
   1060 #elif V8_HOST_ARCH_ARM
   1061 // An undefined macro evaluates to 0, so this applies to Android's Bionic also.
   1062 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
   1063   sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
   1064   sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
   1065   sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
   1066 #else
   1067   sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
   1068   sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
   1069   sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
   1070 #endif  // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
   1071 #elif V8_HOST_ARCH_MIPS
   1072   sample->pc = reinterpret_cast<Address>(mcontext.pc);
   1073   sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
   1074   sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
   1075 #endif  // V8_HOST_ARCH_*
   1076   sampler->SampleStack(sample);
   1077   sampler->Tick(sample);
   1078 }
   1079 
   1080 
   1081 class Sampler::PlatformData : public Malloced {
   1082  public:
   1083   PlatformData() : vm_tid_(GetThreadID()) {}
   1084 
   1085   int vm_tid() const { return vm_tid_; }
   1086 
   1087  private:
   1088   const int vm_tid_;
   1089 };
   1090 
   1091 
   1092 class SignalSender : public Thread {
   1093  public:
   1094   enum SleepInterval {
   1095     HALF_INTERVAL,
   1096     FULL_INTERVAL
   1097   };
   1098 
   1099   static const int kSignalSenderStackSize = 64 * KB;
   1100 
   1101   explicit SignalSender(int interval)
   1102       : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
   1103         vm_tgid_(getpid()),
   1104         interval_(interval) {}
   1105 
   1106   static void InstallSignalHandler() {
   1107     struct sigaction sa;
   1108     sa.sa_sigaction = ProfilerSignalHandler;
   1109     sigemptyset(&sa.sa_mask);
   1110     sa.sa_flags = SA_RESTART | SA_SIGINFO;
   1111     signal_handler_installed_ =
   1112         (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
   1113   }
   1114 
   1115   static void RestoreSignalHandler() {
   1116     if (signal_handler_installed_) {
   1117       sigaction(SIGPROF, &old_signal_handler_, 0);
   1118       signal_handler_installed_ = false;
   1119     }
   1120   }
   1121 
   1122   static void AddActiveSampler(Sampler* sampler) {
   1123     ScopedLock lock(mutex_.Pointer());
   1124     SamplerRegistry::AddActiveSampler(sampler);
   1125     if (instance_ == NULL) {
   1126       // Start a thread that will send SIGPROF signal to VM threads,
   1127       // when CPU profiling will be enabled.
   1128       instance_ = new SignalSender(sampler->interval());
   1129       instance_->Start();
   1130     } else {
   1131       ASSERT(instance_->interval_ == sampler->interval());
   1132     }
   1133   }
   1134 
   1135   static void RemoveActiveSampler(Sampler* sampler) {
   1136     ScopedLock lock(mutex_.Pointer());
   1137     SamplerRegistry::RemoveActiveSampler(sampler);
   1138     if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
   1139       RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
   1140       delete instance_;
   1141       instance_ = NULL;
   1142       RestoreSignalHandler();
   1143     }
   1144   }
   1145 
   1146   // Implement Thread::Run().
   1147   virtual void Run() {
   1148     SamplerRegistry::State state;
   1149     while ((state = SamplerRegistry::GetState()) !=
   1150            SamplerRegistry::HAS_NO_SAMPLERS) {
   1151       bool cpu_profiling_enabled =
   1152           (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
   1153       bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
   1154       if (cpu_profiling_enabled && !signal_handler_installed_) {
   1155         InstallSignalHandler();
   1156       } else if (!cpu_profiling_enabled && signal_handler_installed_) {
   1157         RestoreSignalHandler();
   1158       }
   1159       // When CPU profiling is enabled both JavaScript and C++ code is
   1160       // profiled. We must not suspend.
   1161       if (!cpu_profiling_enabled) {
   1162         if (rate_limiter_.SuspendIfNecessary()) continue;
   1163       }
   1164       if (cpu_profiling_enabled && runtime_profiler_enabled) {
   1165         if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
   1166           return;
   1167         }
   1168         Sleep(HALF_INTERVAL);
   1169         if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
   1170           return;
   1171         }
   1172         Sleep(HALF_INTERVAL);
   1173       } else {
   1174         if (cpu_profiling_enabled) {
   1175           if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
   1176                                                       this)) {
   1177             return;
   1178           }
   1179         }
   1180         if (runtime_profiler_enabled) {
   1181           if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
   1182                                                       NULL)) {
   1183             return;
   1184           }
   1185         }
   1186         Sleep(FULL_INTERVAL);
   1187       }
   1188     }
   1189   }
   1190 
   1191   static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
   1192     if (!sampler->IsProfiling()) return;
   1193     SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
   1194     sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
   1195   }
   1196 
   1197   static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
   1198     if (!sampler->isolate()->IsInitialized()) return;
   1199     sampler->isolate()->runtime_profiler()->NotifyTick();
   1200   }
   1201 
   1202   void SendProfilingSignal(int tid) {
   1203     if (!signal_handler_installed_) return;
   1204     // Glibc doesn't provide a wrapper for tgkill(2).
   1205 #if defined(ANDROID)
   1206     syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
   1207 #else
   1208     syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
   1209 #endif
   1210   }
   1211 
   1212   void Sleep(SleepInterval full_or_half) {
   1213     // Convert ms to us and subtract 100 us to compensate delays
   1214     // occuring during signal delivery.
   1215     useconds_t interval = interval_ * 1000 - 100;
   1216     if (full_or_half == HALF_INTERVAL) interval /= 2;
   1217 #if defined(ANDROID)
   1218     usleep(interval);
   1219 #else
   1220     int result = usleep(interval);
   1221 #ifdef DEBUG
   1222     if (result != 0 && errno != EINTR) {
   1223       fprintf(stderr,
   1224               "SignalSender usleep error; interval = %u, errno = %d\n",
   1225               interval,
   1226               errno);
   1227       ASSERT(result == 0 || errno == EINTR);
   1228     }
   1229 #endif  // DEBUG
   1230     USE(result);
   1231 #endif  // ANDROID
   1232   }
   1233 
   1234   const int vm_tgid_;
   1235   const int interval_;
   1236   RuntimeProfilerRateLimiter rate_limiter_;
   1237 
   1238   // Protects the process wide state below.
   1239   static LazyMutex mutex_;
   1240   static SignalSender* instance_;
   1241   static bool signal_handler_installed_;
   1242   static struct sigaction old_signal_handler_;
   1243 
   1244  private:
   1245   DISALLOW_COPY_AND_ASSIGN(SignalSender);
   1246 };
   1247 
   1248 
   1249 LazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER;
   1250 SignalSender* SignalSender::instance_ = NULL;
   1251 struct sigaction SignalSender::old_signal_handler_;
   1252 bool SignalSender::signal_handler_installed_ = false;
   1253 
   1254 
   1255 Sampler::Sampler(Isolate* isolate, int interval)
   1256     : isolate_(isolate),
   1257       interval_(interval),
   1258       profiling_(false),
   1259       active_(false),
   1260       samples_taken_(0) {
   1261   data_ = new PlatformData;
   1262 }
   1263 
   1264 
   1265 Sampler::~Sampler() {
   1266   ASSERT(!IsActive());
   1267   delete data_;
   1268 }
   1269 
   1270 
   1271 void Sampler::Start() {
   1272   ASSERT(!IsActive());
   1273   SetActive(true);
   1274   SignalSender::AddActiveSampler(this);
   1275 }
   1276 
   1277 
   1278 void Sampler::Stop() {
   1279   ASSERT(IsActive());
   1280   SignalSender::RemoveActiveSampler(this);
   1281   SetActive(false);
   1282 }
   1283 
   1284 
   1285 } }  // namespace v8::internal
   1286