13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Platform specific code for FreeBSD goes here. For the POSIX comaptible parts 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the implementation is in platform-posix.cc. 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <pthread.h> 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <semaphore.h> 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <signal.h> 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/time.h> 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/resource.h> 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/types.h> 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/ucontext.h> 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h> 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/types.h> // mmap & munmap 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/mman.h> // mmap & munmap 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/stat.h> // open 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <sys/fcntl.h> // open 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <unistd.h> // getpagesize 4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// If you don't have execinfo.h then you need devel/libexecinfo from ports. 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <execinfo.h> // backtrace, backtrace_symbols 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <strings.h> // index 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <errno.h> 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdarg.h> 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <limits.h> 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef MAP_TYPE 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 55257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "v8threads.h" 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "platform-posix.h" 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 0 is never a valid thread id on FreeBSD since tids and pids share a 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// name space and pid 0 is used to kill the group (see man 2 kill). 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const pthread_t kNoThread = (pthread_t) 0; 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble ceiling(double x) { 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Correct as on OS X 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-1.0 < x && x < 0.0) { 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -0.0; 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ceil(x); 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic Mutex* limit_mutex = NULL; 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() { 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Seed the random number generator. 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the current time to a 64-bit integer first, before converting it 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to an unsigned. Going directly can cause an overflow and the seed to be 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set to all ones. The seed will be identical for different instances that 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // call this setup code within the same millisecond. 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block srandom(static_cast<unsigned int>(seed)); 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block limit_mutex = CreateMutex(); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() { 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math functions depend on CPU features therefore they are initialized after 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CPU. 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathSetup(); 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 1037f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __asm__ __volatile__("" : : : "memory"); 1047f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch *ptr = value; 1057f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 1067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1077f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 108d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 109d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; // FreeBSD runs on anything. 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::ActivationFrameAlignment() { 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 16 byte alignment on FreeBSD 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 16; 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return t->tm_zone; 125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 129d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = time(NULL); 130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // tm_gmtoff includes any daylight savings offset, so subtract it. 132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>(t->tm_gmtoff * msPerSecond - 133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We keep the lowest and highest addresses mapped as a quick way of 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// determining that pointers are outside the heap (used mostly in assertions 1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification). The estimate is conservative, i.e., not all addresses in 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 'allocated' space are actually allocated to our heap. The range is 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(limit_mutex != NULL); 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(limit_mutex); 14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block highest_ever_allocated = 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Max(highest_ever_allocated, 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool OS::IsOutsideAllocatedSpace(void* address) { 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return address < lowest_ever_allocated || address >= highest_ever_allocated; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocksize_t OS::AllocateAlignment() { 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return getpagesize(); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* OS::Allocate(const size_t requested, 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_t* allocated, 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool executable) { 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t msize = RoundUp(requested, getpagesize()); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mbase == MAP_FAILED) { 17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *allocated = msize; 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocatedSpaceLimits(mbase, msize); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mbase; 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Free(void* buf, const size_t length) { 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1240712): munmap has a return value which is ignored here. 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = munmap(buf, length); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Sleep(int milliseconds) { 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int ms = static_cast<unsigned int>(milliseconds); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block usleep(1000 * ms); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Abort() { 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Redirect to std abort to signal abnormal program termination. 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort(); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::DebugBreak() { 205756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#if (defined(__arm__) || defined(__thumb__)) 206756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# if defined(CAN_USE_ARMV5_INSTRUCTIONS) 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("bkpt 0"); 208756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# endif 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("int $3"); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PosixMemoryMappedFile(FILE* file, void* memory, int size) 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : file_(file), memory_(memory), size_(size) { } 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~PosixMemoryMappedFile(); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void* memory() { return memory_; } 2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file_; 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory_; 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* initial) { 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file = fopen(name, "w+"); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file == NULL) return NULL; 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = fwrite(initial, size, 1, file); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) { 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory = 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new PosixMemoryMappedFile(file, memory, size); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockPosixMemoryMappedFile::~PosixMemoryMappedFile() { 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (memory_) munmap(memory_, size_); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file_); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic unsigned StringToLong(char* buffer) { 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::LogSharedLibraryAddresses() { 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int MAP_LENGTH = 1024; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int fd = open("/proc/self/maps", O_RDONLY); 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fd < 0) return; 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char addr_buffer[11]; 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[0] = '0'; 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[1] = 'x'; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[10] = 0; 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = read(fd, addr_buffer + 2, 8); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 8) break; 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned start = StringToLong(addr_buffer); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, addr_buffer + 2, 1); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) break; 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (addr_buffer[2] != '-') break; 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, addr_buffer + 2, 8); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 8) break; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned end = StringToLong(addr_buffer); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char buffer[MAP_LENGTH]; 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bytes_read = -1; 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bytes_read++; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (bytes_read >= MAP_LENGTH - 1) 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, buffer + bytes_read, 1); 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) break; 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (buffer[bytes_read] != '\n'); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[bytes_read] = 0; 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ignore mappings that are not executable. 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer[3] != 'x') continue; 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* start_of_path = index(buffer, '/'); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There may be no filename in this line. Skip to next. 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_of_path == NULL) continue; 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[bytes_read] = 0; 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end)); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block close(fd); 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 308f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 309f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 310f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 311f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frames_size = frames.length(); 31425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ScopedVector<void*> addresses(frames_size); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int frames_count = backtrace(addresses.start(), frames_size); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke char** symbols = backtrace_symbols(addresses.start(), frames_count); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (symbols == NULL) { 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kStackWalkError; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < frames_count; i++) { 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].address = addresses[i]; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Format a text representation of the frame based on the information 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // available. 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen), 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s", 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbols[i]); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure line termination is in place. 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block free(symbols); 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return frames_count; 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Constants used for mmap. 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFd = -1; 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFdOffset = 0; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::VirtualMemory(size_t size) { 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = ReserveRegion(size); 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_ = size; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(NULL), size_(0) { 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t request_size = RoundUp(size + alignment, 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* reservation = mmap(OS::GetRandomMmapAddr(), 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size, 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (reservation == MAP_FAILED) return; 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address base = static_cast<Address>(reservation); 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address aligned_base = RoundUp(base, alignment); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(base, aligned_base); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Unmap extra memory reserved before and after the desired block. 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_base != base) { 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t prefix_size = static_cast<size_t>(aligned_base - base); 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(base, prefix_size); 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= prefix_size; 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(aligned_size, request_size); 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_size != request_size) { 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t suffix_size = request_size - aligned_size; 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(aligned_base + aligned_size, suffix_size); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= suffix_size; 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(aligned_size == request_size); 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = static_cast<void*>(aligned_base); 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = aligned_size; 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::~VirtualMemory() { 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsReserved()) { 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result = ReleaseRegion(address(), size()); 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(result); 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::IsReserved() { 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return address_ != NULL; 403592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 404592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 405592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid VirtualMemory::Reset() { 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = NULL; 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = 0; 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return CommitRegion(address, size, is_executable); 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return UncommitRegion(address, size); 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) { 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Guard(address, OS::CommitPageSize()); 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* result = mmap(OS::GetRandomMmapAddr(), 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (result == MAP_FAILED) return NULL; 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return result; 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (MAP_FAILED == mmap(base, 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prot, 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_FIXED, 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset)) { 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UpdateAllocatedSpaceLimits(base, size); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) { 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return mmap(base, 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset) != MAP_FAILED; 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return munmap(base, size) == 0; 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_t thread_; // Thread handle for pthread. 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4793fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochThread::Thread(const Options& options) 4808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatformData), 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stack_size_(options.stack_size()) { 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_name(options.name()); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::~Thread() { 4878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* ThreadEntry(void* arg) { 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Thread* thread = reinterpret_cast<Thread*>(arg); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This is also initialized by the first argument to pthread_create() but we 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't know which thread will run first (the original thread or the new 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // one) so we initialize it here too. 496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch thread->data()->thread_ = pthread_self(); 497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread->Run(); 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 5049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 5059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 5069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 5079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Start() { 51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(data_->thread_ != kNoThread); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Join() { 523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pthread_join(data_->thread_, NULL); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t key; 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_create(&key, NULL); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<LocalStorageKey>(key); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_delete(pthread_key); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pthread_getspecific(pthread_key); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_setspecific(pthread_key, value); 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::YieldCPU() { 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sched_yield(); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FreeBSDMutex : public Mutex { 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FreeBSDMutex() { 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutexattr_t attrs; 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutexattr_init(&attrs); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = pthread_mutex_init(&mutex_, &attrs); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~FreeBSDMutex() { pthread_mutex_destroy(&mutex_); } 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual int Lock() { 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutex_lock(&mutex_); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual int Unlock() { 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutex_unlock(&mutex_); 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58544f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual bool TryLock() { 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = pthread_mutex_trylock(&mutex_); 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return false if the lock is busy and locking failed. 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result == EBUSY) { 58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return false; 59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0); // Verify no other errors. 59244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 59444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMutex* OS::CreateMutex() { 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new FreeBSDMutex(); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FreeBSDSemaphore : public Semaphore { 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit FreeBSDSemaphore(int count) { sem_init(&sem_, 0, count); } 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); } 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void Wait(); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual bool Wait(int timeout); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void Signal() { sem_post(&sem_); } 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sem_t sem_; 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid FreeBSDSemaphore::Wait() { 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = sem_wait(&sem_); 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == 0) return; // Successfully got semaphore. 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool FreeBSDSemaphore::Wait(int timeout) { 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const long kOneSecondMicros = 1000000; // NOLINT 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Split timeout into second and nanosecond parts. 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval delta; 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta.tv_usec = timeout % kOneSecondMicros; 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta.tv_sec = timeout / kOneSecondMicros; 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval current_time; 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the current time. 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (gettimeofday(¤t_time, NULL) == -1) { 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate time for end of timeout. 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval end_time; 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block timeradd(¤t_time, &delta, &end_time); 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timespec ts; 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TIMEVAL_TO_TIMESPEC(&end_time, &ts); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = sem_timedwait(&sem_, &ts); 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == 0) return true; // Successfully got semaphore. 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSemaphore* OS::CreateSemaphore(int count) { 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new FreeBSDSemaphore(count); 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic pthread_t GetThreadID() { 66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t thread_id = pthread_self(); 66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return thread_id; 66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 66744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Sampler::PlatformData : public Malloced { 66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block PlatformData() : vm_tid_(GetThreadID()) {} 67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t vm_tid() const { return vm_tid_; } 67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 67344f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t vm_tid_; 67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 67644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(info); 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (signal != SIGPROF) return; 68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = Isolate::UncheckedCurrent(); 68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We require a fully initialized and entered isolate. 68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (v8::Locker::IsActive() && 6878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch !isolate->thread_manager()->IsLockedByCurrentThread()) { 6888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 6898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 69144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sampler* sampler = isolate->logger()->sampler(); 69244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sampler == NULL || !sampler->IsActive()) return; 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample sample_obj; 69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sample == NULL) sample = &sample_obj; 6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Extracting the sample from the context is extremely machine dependent. 69944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block mcontext_t& mcontext = ucontext->uc_mcontext; 70144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->state = isolate->current_vm_state(); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_HOST_ARCH_IA32 70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); 70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); 70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_X64 70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); 70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); 70944f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_ARM 71144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); 71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); 71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->SampleStack(sample); 71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->Tick(sample); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SignalSender : public Thread { 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block enum SleepInterval { 72344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HALF_INTERVAL, 72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block FULL_INTERVAL 72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 72644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSignalSenderStackSize = 64 * KB; 7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 72944f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit SignalSender(int interval) 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), 73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval) {} 73244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void AddActiveSampler(Sampler* sampler) { 7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 73544f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::AddActiveSampler(sampler); 73644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instance_ == NULL) { 73744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Install a signal handler. 73844f0eee88ff00398ff7f715fab053374d808c90dSteve Block struct sigaction sa; 73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa.sa_sigaction = ProfilerSignalHandler; 74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sigemptyset(&sa.sa_mask); 74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa.sa_flags = SA_RESTART | SA_SIGINFO; 74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block signal_handler_installed_ = 74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Start a thread that sends SIGPROF signal to VM threads. 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = new SignalSender(sampler->interval()); 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_->Start(); 74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instance_->interval_ == sampler->interval()); 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void RemoveActiveSampler(Sampler* sampler) { 7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::RemoveActiveSampler(sampler); 75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 7573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete instance_; 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = NULL; 76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Restore the old signal handler. 76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (signal_handler_installed_) { 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sigaction(SIGPROF, &old_signal_handler_, 0); 76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block signal_handler_installed_ = false; 76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Implement Thread::Run(). 77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Run() { 77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::State state; 77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block while ((state = SamplerRegistry::GetState()) != 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::HAS_NO_SAMPLERS) { 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool cpu_profiling_enabled = 77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // When CPU profiling is enabled both JavaScript and C++ code is 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // profiled. We must not suspend. 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!cpu_profiling_enabled) { 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rate_limiter_.SuspendIfNecessary()) continue; 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled && runtime_profiler_enabled) { 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled) { 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block this)) { 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (runtime_profiler_enabled) { 79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block NULL)) { 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(FULL_INTERVAL); 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->IsProfiling()) return; 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->isolate()->runtime_profiler()->NotifyTick(); 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SendProfilingSignal(pthread_t tid) { 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!signal_handler_installed_) return; 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_kill(tid, SIGPROF); 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Sleep(SleepInterval full_or_half) { 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert ms to us and subtract 100 us to compensate delays 82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // occuring during signal delivery. 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block useconds_t interval = interval_ * 1000 - 100; 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (full_or_half == HALF_INTERVAL) interval /= 2; 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = usleep(interval); 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result != 0 && errno != EINTR) { 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block fprintf(stderr, 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block "SignalSender usleep error; interval = %u, errno = %d\n", 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval, 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block errno); 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0 || errno == EINTR); 83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block USE(result); 84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int interval_; 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfilerRateLimiter rate_limiter_; 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Protects the process wide state below. 8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static LazyMutex mutex_; 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static SignalSender* instance_; 84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool signal_handler_installed_; 85044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static struct sigaction old_signal_handler_; 85144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 85344f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(SignalSender); 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; 85744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSignalSender* SignalSender::instance_ = NULL; 85844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstruct sigaction SignalSender::old_signal_handler_; 85944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool SignalSender::signal_handler_installed_ = false; 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 86144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 86344f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 8668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 8678a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data_ = new PlatformData; 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSampler::~Sampler() { 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Start() { 87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(true); 88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender::AddActiveSampler(this); 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Stop() { 88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsActive()); 88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender::RemoveActiveSampler(this); 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(false); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 893