platform-freebsd.cc revision 592a9fc1d8ea420377a2e7efd0600e20b058be2b
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 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 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 0 is never a valid thread id on FreeBSD since tids and pids share a 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// name space and pid 0 is used to kill the group (see man 2 kill). 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const pthread_t kNoThread = (pthread_t) 0; 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble ceiling(double x) { 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Correct as on OS X 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-1.0 < x && x < 0.0) { 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -0.0; 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ceil(x); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic Mutex* limit_mutex = NULL; 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Setup() { 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Seed the random number generator. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the current time to a 64-bit integer first, before converting it 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to an unsigned. Going directly can cause an overflow and the seed to be 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set to all ones. The seed will be identical for different instances that 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // call this setup code within the same millisecond. 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block srandom(static_cast<unsigned int>(seed)); 9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block limit_mutex = CreateMutex(); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __asm__ __volatile__("" : : : "memory"); 967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch *ptr = value; 977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 997f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; // FreeBSD runs on anything. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::ActivationFrameAlignment() { 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 16 byte alignment on FreeBSD 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 16; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return t->tm_zone; 117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = time(NULL); 122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // tm_gmtoff includes any daylight savings offset, so subtract it. 124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>(t->tm_gmtoff * msPerSecond - 125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 128d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We keep the lowest and highest addresses mapped as a quick way of 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// determining that pointers are outside the heap (used mostly in assertions 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and verification). The estimate is conservative, ie, not all addresses in 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 'allocated' space are actually allocated to our heap. The range is 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(limit_mutex != NULL); 14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(limit_mutex); 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block highest_ever_allocated = 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Max(highest_ever_allocated, 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool OS::IsOutsideAllocatedSpace(void* address) { 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return address < lowest_ever_allocated || address >= highest_ever_allocated; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocksize_t OS::AllocateAlignment() { 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return getpagesize(); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* OS::Allocate(const size_t requested, 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_t* allocated, 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool executable) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t msize = RoundUp(requested, getpagesize()); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mbase == MAP_FAILED) { 16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *allocated = msize; 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocatedSpaceLimits(mbase, msize); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mbase; 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Free(void* buf, const size_t length) { 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1240712): munmap has a return value which is ignored here. 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = munmap(buf, length); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Sleep(int milliseconds) { 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int ms = static_cast<unsigned int>(milliseconds); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block usleep(1000 * ms); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Abort() { 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Redirect to std abort to signal abnormal program termination. 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort(); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::DebugBreak() { 197756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#if (defined(__arm__) || defined(__thumb__)) 198756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# if defined(CAN_USE_ARMV5_INSTRUCTIONS) 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("bkpt 0"); 200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# endif 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("int $3"); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PosixMemoryMappedFile(FILE* file, void* memory, int size) 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : file_(file), memory_(memory), size_(size) { } 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~PosixMemoryMappedFile(); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void* memory() { return memory_; } 2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file_; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory_; 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* initial) { 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file = fopen(name, "w+"); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file == NULL) return NULL; 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = fwrite(initial, size, 1, file); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) { 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file); 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory = 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new PosixMemoryMappedFile(file, memory, size); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockPosixMemoryMappedFile::~PosixMemoryMappedFile() { 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (memory_) munmap(memory_, size_); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file_); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic unsigned StringToLong(char* buffer) { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::LogSharedLibraryAddresses() { 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int MAP_LENGTH = 1024; 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int fd = open("/proc/self/maps", O_RDONLY); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fd < 0) return; 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char addr_buffer[11]; 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[0] = '0'; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[1] = 'x'; 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[10] = 0; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = read(fd, addr_buffer + 2, 8); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 8) break; 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned start = StringToLong(addr_buffer); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, addr_buffer + 2, 1); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) break; 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (addr_buffer[2] != '-') break; 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, addr_buffer + 2, 8); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 8) break; 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned end = StringToLong(addr_buffer); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char buffer[MAP_LENGTH]; 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bytes_read = -1; 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bytes_read++; 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (bytes_read >= MAP_LENGTH - 1) 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, buffer + bytes_read, 1); 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) break; 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (buffer[bytes_read] != '\n'); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[bytes_read] = 0; 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ignore mappings that are not executable. 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer[3] != 'x') continue; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* start_of_path = index(buffer, '/'); 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There may be no filename in this line. Skip to next. 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_of_path == NULL) continue; 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[bytes_read] = 0; 29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end)); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block close(fd); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 301f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 302f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 303f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frames_size = frames.length(); 30625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ScopedVector<void*> addresses(frames_size); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int frames_count = backtrace(addresses.start(), frames_size); 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke char** symbols = backtrace_symbols(addresses.start(), frames_count); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (symbols == NULL) { 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kStackWalkError; 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < frames_count; i++) { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].address = addresses[i]; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Format a text representation of the frame based on the information 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // available. 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen), 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s", 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbols[i]); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure line termination is in place. 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block free(symbols); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return frames_count; 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Constants used for mmap. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFd = -1; 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFdOffset = 0; 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::VirtualMemory(size_t size) { 339592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch address_ = ReserveRegion(size); 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_ = size; 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 344592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch : address_(NULL), size_(0) { 346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size_t request_size = RoundUp(size + alignment, 348592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 349592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch void* reservation = mmap(OS::GetRandomMmapAddr(), 350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch request_size, 351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch PROT_NONE, 352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFd, 354592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFdOffset); 355592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (reservation == MAP_FAILED) return; 356592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 357592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Address base = static_cast<Address>(reservation); 358592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Address aligned_base = RoundUp(base, alignment); 359592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_LE(base, aligned_base); 360592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 361592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Unmap extra memory reserved before and after the desired block. 362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (aligned_base != base) { 363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size_t prefix_size = static_cast<size_t>(aligned_base - base); 364592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch OS::Free(base, prefix_size); 365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch request_size -= prefix_size; 366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 369592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_LE(aligned_size, request_size); 370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (aligned_size != request_size) { 372592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size_t suffix_size = request_size - aligned_size; 373592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch OS::Free(aligned_base + aligned_size, suffix_size); 374592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch request_size -= suffix_size; 375592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 376592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 377592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(aligned_size == request_size); 378592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 379592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch address_ = static_cast<void*>(aligned_base); 380592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size_ = aligned_size; 381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 382592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 383592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::~VirtualMemory() { 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsReserved()) { 386592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool result = ReleaseRegion(address(), size()); 387592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(result); 388592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch USE(result); 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::IsReserved() { 394592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return address_ != NULL; 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 398592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid VirtualMemory::Reset() { 399592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch address_ = NULL; 400592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size_ = 0; 401592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 402592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 403592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 404592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 405592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return CommitRegion(address, size, is_executable); 406592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 407592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 408592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 409592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 410592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return UncommitRegion(address, size); 411592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 412592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 413592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 414592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool VirtualMemory::Guard(void* address) { 415592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch OS::Guard(address, OS::CommitPageSize()); 416592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return true; 417592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 418592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 419592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 420592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 421592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch void* result = mmap(OS::GetRandomMmapAddr(), 422592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size, 423592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch PROT_NONE, 424592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFd, 426592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFdOffset); 427592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 428592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (result == MAP_FAILED) return NULL; 429592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 430592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return result; 431592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 432592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 433592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 434592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 435592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 436592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (MAP_FAILED == mmap(base, 437592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size, 438592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch prot, 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_FIXED, 440592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFd, 441592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFdOffset)) { 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch UpdateAllocatedSpaceLimits(base, size); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 450592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) { 451592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return mmap(base, 452592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch size, 453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch PROT_NONE, 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, 455592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFd, 456592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch kMmapFdOffset) != MAP_FAILED; 457592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 458592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 459592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 460592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 461592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return munmap(base, size) == 0; 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_t thread_; // Thread handle for pthread. 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochThread::Thread(const Options& options) 4728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatformData), 47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_size_(options.stack_size) { 47444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_name(options.name); 4759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 4769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 4779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 4783fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochThread::Thread(const char* name) 4798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatformData), 48044f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_size_(0) { 4811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block set_name(name); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::~Thread() { 4868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* ThreadEntry(void* arg) { 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Thread* thread = reinterpret_cast<Thread*>(arg); 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This is also initialized by the first argument to pthread_create() but we 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't know which thread will run first (the original thread or the new 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // one) so we initialize it here too. 495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch thread->data()->thread_ = pthread_self(); 496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread->Run(); 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 5039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 5049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 5059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 5069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Start() { 50944f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 51044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 51144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 51244f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 51344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 51444f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 51544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(data_->thread_ != kNoThread); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Join() { 522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pthread_join(data_->thread_, NULL); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t key; 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_create(&key, NULL); 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<LocalStorageKey>(key); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_delete(pthread_key); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pthread_getspecific(pthread_key); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_setspecific(pthread_key, value); 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::YieldCPU() { 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sched_yield(); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FreeBSDMutex : public Mutex { 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FreeBSDMutex() { 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutexattr_t attrs; 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutexattr_init(&attrs); 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = pthread_mutex_init(&mutex_, &attrs); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~FreeBSDMutex() { pthread_mutex_destroy(&mutex_); } 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual int Lock() { 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutex_lock(&mutex_); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual int Unlock() { 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutex_unlock(&mutex_); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual bool TryLock() { 58544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = pthread_mutex_trylock(&mutex_); 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return false if the lock is busy and locking failed. 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result == EBUSY) { 58844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return false; 58944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 59044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0); // Verify no other errors. 59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 59244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 59344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMutex* OS::CreateMutex() { 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new FreeBSDMutex(); 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FreeBSDSemaphore : public Semaphore { 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit FreeBSDSemaphore(int count) { sem_init(&sem_, 0, count); } 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); } 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void Wait(); 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual bool Wait(int timeout); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void Signal() { sem_post(&sem_); } 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sem_t sem_; 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid FreeBSDSemaphore::Wait() { 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = sem_wait(&sem_); 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == 0) return; // Successfully got semaphore. 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool FreeBSDSemaphore::Wait(int timeout) { 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const long kOneSecondMicros = 1000000; // NOLINT 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Split timeout into second and nanosecond parts. 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval delta; 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta.tv_usec = timeout % kOneSecondMicros; 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta.tv_sec = timeout / kOneSecondMicros; 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval current_time; 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the current time. 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (gettimeofday(¤t_time, NULL) == -1) { 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate time for end of timeout. 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval end_time; 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block timeradd(¤t_time, &delta, &end_time); 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timespec ts; 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TIMEVAL_TO_TIMESPEC(&end_time, &ts); 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = sem_timedwait(&sem_, &ts); 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == 0) return true; // Successfully got semaphore. 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSemaphore* OS::CreateSemaphore(int count) { 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new FreeBSDSemaphore(count); 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 66044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic pthread_t GetThreadID() { 66144f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t thread_id = pthread_self(); 66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return thread_id; 66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 66644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Sampler::PlatformData : public Malloced { 66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block PlatformData() : vm_tid_(GetThreadID()) {} 66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t vm_tid() const { return vm_tid_; } 67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 67344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t vm_tid_; 67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(info); 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (signal != SIGPROF) return; 68044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = Isolate::UncheckedCurrent(); 68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We require a fully initialized and entered isolate. 68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (v8::Locker::IsActive() && 6868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch !isolate->thread_manager()->IsLockedByCurrentThread()) { 6878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 6888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sampler* sampler = isolate->logger()->sampler(); 69144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sampler == NULL || !sampler->IsActive()) return; 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample sample_obj; 69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sample == NULL) sample = &sample_obj; 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 69744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Extracting the sample from the context is extremely machine dependent. 69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 69944f0eee88ff00398ff7f715fab053374d808c90dSteve Block mcontext_t& mcontext = ucontext->uc_mcontext; 70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->state = isolate->current_vm_state(); 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_HOST_ARCH_IA32 70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); 70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); 70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_X64 70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); 70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); 70844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_ARM 71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); 71144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); 71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->SampleStack(sample); 71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->Tick(sample); 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SignalSender : public Thread { 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 72144f0eee88ff00398ff7f715fab053374d808c90dSteve Block enum SleepInterval { 72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HALF_INTERVAL, 72344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FULL_INTERVAL 72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 72644f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit SignalSender(int interval) 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : Thread("SignalSender"), 72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval) {} 72944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 73044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void AddActiveSampler(Sampler* sampler) { 73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(mutex_); 73244f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::AddActiveSampler(sampler); 73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instance_ == NULL) { 73444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Install a signal handler. 73544f0eee88ff00398ff7f715fab053374d808c90dSteve Block struct sigaction sa; 73644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa.sa_sigaction = ProfilerSignalHandler; 73744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sigemptyset(&sa.sa_mask); 73844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa.sa_flags = SA_RESTART | SA_SIGINFO; 73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block signal_handler_installed_ = 74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Start a thread that sends SIGPROF signal to VM threads. 74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = new SignalSender(sampler->interval()); 74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_->Start(); 74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instance_->interval_ == sampler->interval()); 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void RemoveActiveSampler(Sampler* sampler) { 75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(mutex_); 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::RemoveActiveSampler(sampler); 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete instance_; 75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = NULL; 75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Restore the old signal handler. 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (signal_handler_installed_) { 76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sigaction(SIGPROF, &old_signal_handler_, 0); 76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block signal_handler_installed_ = false; 76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Implement Thread::Run(). 76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Run() { 76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::State state; 76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block while ((state = SamplerRegistry::GetState()) != 77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::HAS_NO_SAMPLERS) { 77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool cpu_profiling_enabled = 77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // When CPU profiling is enabled both JavaScript and C++ code is 77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // profiled. We must not suspend. 77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!cpu_profiling_enabled) { 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rate_limiter_.SuspendIfNecessary()) continue; 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled && runtime_profiler_enabled) { 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled) { 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, 79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block this)) { 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (runtime_profiler_enabled) { 79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, 79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block NULL)) { 79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(FULL_INTERVAL); 80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->IsProfiling()) return; 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->isolate()->runtime_profiler()->NotifyTick(); 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SendProfilingSignal(pthread_t tid) { 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!signal_handler_installed_) return; 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_kill(tid, SIGPROF); 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 82244f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Sleep(SleepInterval full_or_half) { 82344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert ms to us and subtract 100 us to compensate delays 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // occuring during signal delivery. 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block useconds_t interval = interval_ * 1000 - 100; 82644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (full_or_half == HALF_INTERVAL) interval /= 2; 82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = usleep(interval); 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result != 0 && errno != EINTR) { 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block fprintf(stderr, 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block "SignalSender usleep error; interval = %u, errno = %d\n", 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval, 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block errno); 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0 || errno == EINTR); 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block USE(result); 83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int interval_; 84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfilerRateLimiter rate_limiter_; 84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Protects the process wide state below. 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Mutex* mutex_; 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static SignalSender* instance_; 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool signal_handler_installed_; 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static struct sigaction old_signal_handler_; 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(SignalSender); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMutex* SignalSender::mutex_ = OS::CreateMutex(); 85344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSignalSender* SignalSender::instance_ = NULL; 85444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstruct sigaction SignalSender::old_signal_handler_; 85544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool SignalSender::signal_handler_installed_ = false; 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 85744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 85844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 85944f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 86044f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 8628a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 8638a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block data_ = new PlatformData; 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSampler::~Sampler() { 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Start() { 87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(true); 87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender::AddActiveSampler(this); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Stop() { 88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsActive()); 88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender::RemoveActiveSampler(this); 88444f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(false); 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 889