13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Redistribution and use in source and binary forms, with or without 3d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// modification, are permitted provided that the following conditions are 4d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// met: 5d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 6d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// * Redistributions of source code must retain the above copyright 7d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// notice, this list of conditions and the following disclaimer. 8d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// * Redistributions in binary form must reproduce the above 9d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// copyright notice, this list of conditions and the following 10d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// disclaimer in the documentation and/or other materials provided 11d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// with the distribution. 12d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// * Neither the name of Google Inc. nor the names of its 13d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// contributors may be used to endorse or promote products derived 14d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// from this software without specific prior written permission. 15d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 16d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Platform specific code for OpenBSD and NetBSD goes here. For the POSIX 293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// comaptible parts the implementation is in platform-posix.cc. 30d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 31d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <pthread.h> 32d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <semaphore.h> 33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <signal.h> 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/time.h> 35d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/resource.h> 363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <sys/syscall.h> 37d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/types.h> 38d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <stdlib.h> 39d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 40d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/types.h> // mmap & munmap 41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/mman.h> // mmap & munmap 42d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/stat.h> // open 433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <fcntl.h> // open 443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include <unistd.h> // sysconf 45d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <execinfo.h> // backtrace, backtrace_symbols 46d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <strings.h> // index 47d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <errno.h> 48d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <stdarg.h> 49d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 50d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef MAP_TYPE 51d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 52d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "v8.h" 53d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "platform-posix.h" 55d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "platform.h" 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8threads.h" 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 60d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blocknamespace v8 { 61d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blocknamespace internal { 62d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// 0 is never a valid thread id on Linux and OpenBSD since tids and pids share a 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// name space and pid 0 is reserved (see man 2 kill). 65d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const pthread_t kNoThread = (pthread_t) 0; 66d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 67d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 68d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockdouble ceiling(double x) { 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ceil(x); 70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 71d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 72d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Mutex* limit_mutex = NULL; 743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void* GetRandomMmapAddr() { 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that the current isolate isn't set up in a call path via 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CpuFeatures::Probe. We don't care about randomization in this case because 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the code page is immediately freed. 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate != NULL) { 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef V8_TARGET_ARCH_X64 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint64_t rnd1 = V8::RandomPrivate(isolate); 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint64_t rnd2 = V8::RandomPrivate(isolate); 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint64_t raw_addr = (rnd1 << 32) ^ rnd2; 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Currently available CPUs have 48 bits of virtual addressing. Truncate 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the hint address to 46 bits to give the kernel a fighting chance of 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // fulfilling our placement request. 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch raw_addr &= V8_UINT64_C(0x3ffffffff000); 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t raw_addr = V8::RandomPrivate(isolate); 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The range 0x20000000 - 0x60000000 is relatively unpopulated across a 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // variety of ASLR modes (PAE kernel, NX compat mode, etc). 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch raw_addr &= 0x3ffff000; 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch raw_addr += 0x20000000; 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return reinterpret_cast<void*>(raw_addr); 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return NULL; 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() { 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Seed the random number generator. We preserve microsecond resolution. 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint64_t seed = Ticks() ^ (getpid() << 16); 10685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch srandom(static_cast<unsigned int>(seed)); 10785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch limit_mutex = CreateMutex(); 108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 110d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() { 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math functions depend on CPU features therefore they are initialized after 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CPU. 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathSetup(); 1153bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 1163bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1173bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 118d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return 0; 120d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 121d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint OS::ActivationFrameAlignment() { 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // With gcc 4.4 the tree vectorization optimizer can generate code 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that requires 16 byte alignment such as movdqa on x86. 126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 16; 127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __asm__ __volatile__("" : : : "memory"); 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // An x86 store acts as a release barrier. 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *ptr = value; 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return t->tm_zone; 143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = time(NULL); 148d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // tm_gmtoff includes any daylight savings offset, so subtract it. 150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>(t->tm_gmtoff * msPerSecond - 151d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// We keep the lowest and highest addresses mapped as a quick way of 156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// determining that pointers are outside the heap (used mostly in assertions 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification). The estimate is conservative, i.e., not all addresses in 158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 'allocated' space are actually allocated to our heap. The range is 159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 1653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(limit_mutex != NULL); 1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ScopedLock lock(limit_mutex); 1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block highest_ever_allocated = 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Max(highest_ever_allocated, 171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool OS::IsOutsideAllocatedSpace(void* address) { 176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return address < lowest_ever_allocated || address >= highest_ever_allocated; 177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blocksize_t OS::AllocateAlignment() { 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return sysconf(_SC_PAGESIZE); 182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid* OS::Allocate(const size_t requested, 186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block size_t* allocated, 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_executable) { 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const size_t msize = RoundUp(requested, AllocateAlignment()); 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* addr = GetRandomMmapAddr(); 1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mbase == MAP_FAILED) { 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LOG(i::Isolate::Current(), 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringEvent("OS::Allocate", "mmap failed")); 195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return NULL; 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *allocated = msize; 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UpdateAllocatedSpaceLimits(mbase, msize); 199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return mbase; 200d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 201d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::Free(void* address, const size_t size) { 2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // TODO(1240712): munmap has a return value which is ignored here. 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int result = munmap(address, size); 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(result); 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Sleep(int milliseconds) { 212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned int ms = static_cast<unsigned int>(milliseconds); 213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block usleep(1000 * ms); 214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 216d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Abort() { 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Redirect to std abort to signal abnormal program termination. 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block abort(); 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::DebugBreak() { 224d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block asm("int $3"); 225d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 226d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 227d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 228d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 229d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 230d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PosixMemoryMappedFile(FILE* file, void* memory, int size) 231d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block : file_(file), memory_(memory), size_(size) { } 232d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~PosixMemoryMappedFile(); 233d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void* memory() { return memory_; } 2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 235d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 236d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FILE* file_; 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* memory_; 238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int size_; 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* initial) { 257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FILE* file = fopen(name, "w+"); 258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (file == NULL) return NULL; 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = fwrite(initial, size, 1, file); 260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result < 1) { 261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block fclose(file); 262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return NULL; 263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* memory = 265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new PosixMemoryMappedFile(file, memory, size); 267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 270d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockPosixMemoryMappedFile::~PosixMemoryMappedFile() { 2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (memory_) OS::Free(memory_, size_); 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block fclose(file_); 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::LogSharedLibraryAddresses() { 2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This function assumes that the layout of the file is as follows: 2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we encounter an unexpected situation we abort scanning further entries. 2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FILE* fp = fopen("/proc/self/maps", "r"); 2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fp == NULL) return; 2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate enough room to be able to store a full file name. 2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int kLibNameLen = FILENAME_MAX + 1; 2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch i::Isolate* isolate = ISOLATE; 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This loop will terminate once the scanning hits an EOF. 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block while (true) { 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t start, end; 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch char attr_r, attr_w, attr_x, attr_p; 2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Parse the addresses and permission bits at the beginning of the line. 2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int c; 2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Found a read-only executable entry. Skip characters until we reach 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the beginning of the filename or the end of the line. 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch do { 3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch c = getc(fp); 3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } while ((c != EOF) && (c != '\n') && (c != '/')); 3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (c == EOF) break; // EOF: Was unexpected, just exit. 3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Process the filename if found. 3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (c == '/') { 3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ungetc(c, fp); // Push the '/' back into the stream to be read below. 3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read to the end of the line. Exit if the read fails. 3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fgets(lib_name, kLibNameLen, fp) == NULL) break; 3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Drop the newline character read by fgets. We do not need to check 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // for a zero-length string because we know that we at least read the 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // '/' character. 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lib_name[strlen(lib_name) - 1] = '\0'; 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // No library name found, just record the raw address range. 3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch snprintf(lib_name, kLibNameLen, 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LOG(isolate, SharedLibraryEvent(lib_name, start, end)); 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Entry not describing executable data. Skip to end of line to set up 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // reading the next entry. 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch do { 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch c = getc(fp); 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } while ((c != EOF) && (c != '\n')); 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (c == EOF) break; 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch free(lib_name); 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fclose(fp); 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const char kGCFakeMmap[] = "/tmp/__v8_gc__"; 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 339f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Support for ll_prof.py. 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The Linux profiler built into the kernel logs all mmap's with 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // PROT_EXEC so that analysis tools can properly attribute ticks. We 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // do a mmap with a name known by ll_prof.py and immediately munmap 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it. This injects a GC marker into the stream of events generated 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // by the kernel and allows us to synchronize V8 code log and the 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // kernel log. 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = sysconf(_SC_PAGESIZE); 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FILE* f = fopen(kGCFakeMmap, "w+"); 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE, 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fileno(f), 0); 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(addr != MAP_FAILED); 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(addr, size); 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fclose(f); 355f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 356f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 357f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // backtrace is a glibc extension. 3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int frames_size = frames.length(); 3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ScopedVector<void*> addresses(frames_size); 3623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int frames_count = backtrace(addresses.start(), frames_size); 3643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char** symbols = backtrace_symbols(addresses.start(), frames_count); 3663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (symbols == NULL) { 3673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return kStackWalkError; 3683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 3693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < frames_count; i++) { 3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch frames[i].address = addresses[i]; 3723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Format a text representation of the frame based on the information 3733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // available. 3743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen), 3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch "%s", 3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch symbols[i]); 3773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Make sure line termination is in place. 3783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; 3793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 3803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch free(symbols); 3823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return frames_count; 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Constants used for mmap. 388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const int kMmapFd = -1; 389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const int kMmapFdOffset = 0; 390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockVirtualMemory::VirtualMemory(size_t size) { 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = ReserveRegion(size); 395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block size_ = size; 396d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 398d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(NULL), size_(0) { 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t request_size = RoundUp(size + alignment, 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* reservation = mmap(GetRandomMmapAddr(), 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size, 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (reservation == MAP_FAILED) return; 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address base = static_cast<Address>(reservation); 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address aligned_base = RoundUp(base, alignment); 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(base, aligned_base); 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Unmap extra memory reserved before and after the desired block. 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_base != base) { 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t prefix_size = static_cast<size_t>(aligned_base - base); 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(base, prefix_size); 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= prefix_size; 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(aligned_size, request_size); 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_size != request_size) { 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t suffix_size = request_size - aligned_size; 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(aligned_base + aligned_size, suffix_size); 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= suffix_size; 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(aligned_size == request_size); 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = static_cast<void*>(aligned_base); 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = aligned_size; 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 439d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockVirtualMemory::~VirtualMemory() { 440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (IsReserved()) { 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result = ReleaseRegion(address(), size()); 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(result); 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool VirtualMemory::IsReserved() { 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return address_ != NULL; 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid VirtualMemory::Reset() { 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = NULL; 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = 0; 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return CommitRegion(address, size, is_executable); 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return UncommitRegion(address, size); 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) { 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Guard(address, OS::CommitPageSize()); 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* result = mmap(GetRandomMmapAddr(), 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (result == MAP_FAILED) return NULL; 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return result; 486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (MAP_FAILED == mmap(base, 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prot, 494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block MAP_PRIVATE | MAP_ANON | MAP_FIXED, 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset)) { 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return false; 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UpdateAllocatedSpaceLimits(base, size); 501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return true; 502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) { 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return mmap(base, 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 5093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset) != MAP_FAILED; 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return munmap(base, size) == 0; 517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PlatformData() : thread_(kNoThread) {} 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_t thread_; // Thread handle for pthread. 525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5273fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochThread::Thread(const Options& options) 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : data_(new PlatformData()), 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stack_size_(options.stack_size()) { 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_name(options.name()); 531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 534d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockThread::~Thread() { 5358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void* ThreadEntry(void* arg) { 540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Thread* thread = reinterpret_cast<Thread*>(arg); 541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is also initialized by the first argument to pthread_create() but we 542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // don't know which thread will run first (the original thread or the new 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // one) so we initialize it here too. 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef PR_SET_NAME 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prctl(PR_SET_NAME, 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reinterpret_cast<unsigned long>(thread->name()), // NOLINT 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 0, 0, 0); 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 5498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread->data()->thread_ = pthread_self(); 5508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block thread->Run(); 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return NULL; 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 5569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 5579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 5589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 5599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 5609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::Start() { 56344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 56444f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 56544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 56644f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 56744f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 56944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(data_->thread_ != kNoThread); 572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::Join() { 5768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_join(data_->thread_, NULL); 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 580d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t key; 582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_key_create(&key, NULL); 583d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(result); 584d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 585d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<LocalStorageKey>(key); 586d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 587d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 588d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_key_delete(pthread_key); 592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(result); 593d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return pthread_getspecific(pthread_key); 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_setspecific(pthread_key, value); 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::YieldCPU() { 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sched_yield(); 611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass OpenBSDMutex : public Mutex { 615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block OpenBSDMutex() { 617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_mutexattr_t attrs; 618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_mutexattr_init(&attrs); 619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = pthread_mutex_init(&mutex_, &attrs); 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~OpenBSDMutex() { pthread_mutex_destroy(&mutex_); } 628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual int Lock() { 630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_mutex_lock(&mutex_); 631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return result; 632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual int Unlock() { 635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_mutex_unlock(&mutex_); 636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return result; 637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch virtual bool TryLock() { 6403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int result = pthread_mutex_trylock(&mutex_); 6413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Return false if the lock is busy and locking failed. 6423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (result == EBUSY) { 6433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 6443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(result == 0); // Verify no other errors. 6463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return true; 6473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 649d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 650d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 651d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 652d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 653d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 654d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockMutex* OS::CreateMutex() { 655d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new OpenBSDMutex(); 656d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 657d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 658d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 659d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass OpenBSDSemaphore : public Semaphore { 660d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 661d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit OpenBSDSemaphore(int count) { sem_init(&sem_, 0, count); } 662d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~OpenBSDSemaphore() { sem_destroy(&sem_); } 663d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 664d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void Wait(); 665d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual bool Wait(int timeout); 666d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void Signal() { sem_post(&sem_); } 667d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 668d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sem_t sem_; 669d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 670d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 671d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 672d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OpenBSDSemaphore::Wait() { 673d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block while (true) { 674d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = sem_wait(&sem_); 675d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result == 0) return; // Successfully got semaphore. 676d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 677d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 678d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 679d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 680d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifndef TIMEVAL_TO_TIMESPEC 6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ 6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (ts)->tv_sec = (tv)->tv_sec; \ 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (ts)->tv_nsec = (tv)->tv_usec * 1000; \ 6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} while (false) 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 689d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool OpenBSDSemaphore::Wait(int timeout) { 690d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const long kOneSecondMicros = 1000000; // NOLINT 691d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 692d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Split timeout into second and nanosecond parts. 693d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timeval delta; 694d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delta.tv_usec = timeout % kOneSecondMicros; 695d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delta.tv_sec = timeout / kOneSecondMicros; 696d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 697d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timeval current_time; 698d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Get the current time. 699d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (gettimeofday(¤t_time, NULL) == -1) { 700d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return false; 701d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 702d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 703d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate time for end of timeout. 704d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timeval end_time; 705d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block timeradd(¤t_time, &delta, &end_time); 706d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 707d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timespec ts; 708d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TIMEVAL_TO_TIMESPEC(&end_time, &ts); 7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int to = ts.tv_sec; 7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 712d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block while (true) { 713d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = sem_trywait(&sem_); 714d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result == 0) return true; // Successfully got semaphore. 7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!to) return false; // Timeout. 716d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch usleep(ts.tv_nsec / 1000); 7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch to--; 719d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 720d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 721d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 722d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockSemaphore* OS::CreateSemaphore(int count) { 723d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new OpenBSDSemaphore(count); 724d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 725d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 726d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic pthread_t GetThreadID() { 7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return pthread_self(); 7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 731d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 732d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(info); 733d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (signal != SIGPROF) return; 7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We require a fully initialized and entered isolate. 7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (v8::Locker::IsActive() && 7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch !isolate->thread_manager()->IsLockedByCurrentThread()) { 7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 743d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Sampler* sampler = isolate->logger()->sampler(); 7453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (sampler == NULL || !sampler->IsActive()) return; 7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TickSample sample_obj; 7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (sample == NULL) sample = &sample_obj; 7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Extracting the sample from the context is extremely machine dependent. 75285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch sample->state = isolate->current_vm_state(); 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef __NetBSD__ 7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mcontext_t& mcontext = ucontext->uc_mcontext; 7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if V8_HOST_ARCH_IA32 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]); 7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]); 7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]); 7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#elif V8_HOST_ARCH_X64 7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]); 7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]); 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]); 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif // V8_HOST_ARCH 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else // OpenBSD 7663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#if V8_HOST_ARCH_IA32 7673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->pc = reinterpret_cast<Address>(ucontext->sc_eip); 7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->sp = reinterpret_cast<Address>(ucontext->sc_esp); 7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp); 7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#elif V8_HOST_ARCH_X64 7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->pc = reinterpret_cast<Address>(ucontext->sc_rip); 7723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp); 7733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp); 7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif // V8_HOST_ARCH 7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif // __NetBSD__ 7763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sampler->SampleStack(sample); 7773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sampler->Tick(sample); 778d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 779d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 780d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass Sampler::PlatformData : public Malloced { 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public: 7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PlatformData() : vm_tid_(GetThreadID()) {} 7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pthread_t vm_tid() const { return vm_tid_; } 7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pthread_t vm_tid_; 7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}; 7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass SignalSender : public Thread { 793d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch enum SleepInterval { 7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HALF_INTERVAL, 7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FULL_INTERVAL 7973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSignalSenderStackSize = 64 * KB; 8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch explicit SignalSender(int interval) 8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), 8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch vm_tgid_(getpid()), 8043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch interval_(interval) {} 8053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static void InstallSignalHandler() { 8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch struct sigaction sa; 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sa.sa_sigaction = ProfilerSignalHandler; 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sigemptyset(&sa.sa_mask); 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sa.sa_flags = SA_RESTART | SA_SIGINFO; 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch signal_handler_installed_ = 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static void RestoreSignalHandler() { 8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (signal_handler_installed_) { 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch sigaction(SIGPROF, &old_signal_handler_, 0); 8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch signal_handler_installed_ = false; 8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void AddActiveSampler(Sampler* sampler) { 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::AddActiveSampler(sampler); 8253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (instance_ == NULL) { 8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Start a thread that will send SIGPROF signal to VM threads, 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // when CPU profiling will be enabled. 8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instance_ = new SignalSender(sampler->interval()); 8293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instance_->Start(); 8303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instance_->interval_ == sampler->interval()); 8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void RemoveActiveSampler(Sampler* sampler) { 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 8373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::RemoveActiveSampler(sampler); 8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 8393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 8403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch delete instance_; 8413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instance_ = NULL; 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RestoreSignalHandler(); 8433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Implement Thread::Run(). 8473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch virtual void Run() { 8483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::State state; 8493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while ((state = SamplerRegistry::GetState()) != 8503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::HAS_NO_SAMPLERS) { 8513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool cpu_profiling_enabled = 8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 8533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cpu_profiling_enabled && !signal_handler_installed_) { 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch InstallSignalHandler(); 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (!cpu_profiling_enabled && signal_handler_installed_) { 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch RestoreSignalHandler(); 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // When CPU profiling is enabled both JavaScript and C++ code is 8603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // profiled. We must not suspend. 8613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!cpu_profiling_enabled) { 8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (rate_limiter_.SuspendIfNecessary()) continue; 8633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (cpu_profiling_enabled && runtime_profiler_enabled) { 8653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 8663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 8673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Sleep(HALF_INTERVAL); 8693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 8703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 8713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Sleep(HALF_INTERVAL); 8733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 8743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (cpu_profiling_enabled) { 8753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, 8763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch this)) { 8773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 8783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (runtime_profiler_enabled) { 8813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, 8823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch NULL)) { 8833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 8843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Sleep(FULL_INTERVAL); 8873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 8923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!sampler->IsProfiling()) return; 8933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 8943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 8953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 8983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!sampler->isolate()->IsInitialized()) return; 8993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sampler->isolate()->runtime_profiler()->NotifyTick(); 9003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void SendProfilingSignal(pthread_t tid) { 9033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!signal_handler_installed_) return; 9043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch pthread_kill(tid, SIGPROF); 9053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Sleep(SleepInterval full_or_half) { 9083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Convert ms to us and subtract 100 us to compensate delays 9093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // occuring during signal delivery. 9103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch useconds_t interval = interval_ * 1000 - 100; 9113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (full_or_half == HALF_INTERVAL) interval /= 2; 9123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int result = usleep(interval); 9133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef DEBUG 9143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (result != 0 && errno != EINTR) { 9153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch fprintf(stderr, 9163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch "SignalSender usleep error; interval = %u, errno = %d\n", 9173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch interval, 9183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch errno); 9193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(result == 0 || errno == EINTR); 9203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif 9223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch USE(result); 923d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 924d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 9253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int vm_tgid_; 9263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int interval_; 9273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfilerRateLimiter rate_limiter_; 9283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Protects the process wide state below. 9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static LazyMutex mutex_; 9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static SignalSender* instance_; 9323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool signal_handler_installed_; 9333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static struct sigaction old_signal_handler_; 9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 9363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DISALLOW_COPY_AND_ASSIGN(SignalSender); 937d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 938d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; 9413fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochSignalSender* SignalSender::instance_ = NULL; 9423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstruct sigaction SignalSender::old_signal_handler_; 9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool SignalSender::signal_handler_installed_ = false; 9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 945d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 94644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 94744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 94844f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 9508a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 9518a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 9523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch data_ = new PlatformData; 953d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 954d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 955d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 956d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockSampler::~Sampler() { 9573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!IsActive()); 958d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delete data_; 959d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 960d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 961d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 962d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Sampler::Start() { 9633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!IsActive()); 9643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SetActive(true); 9653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SignalSender::AddActiveSampler(this); 966d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 967d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 968d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 969d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Sampler::Stop() { 9703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsActive()); 9713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SignalSender::RemoveActiveSampler(this); 9723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SetActive(false); 973d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 974d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 975d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 976d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} } // namespace v8::internal 977