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" 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 0 is never a valid thread id on FreeBSD since tids and pids share a 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// name space and pid 0 is used to kill the group (see man 2 kill). 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const pthread_t kNoThread = (pthread_t) 0; 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble ceiling(double x) { 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Correct as on OS X 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (-1.0 < x && x < 0.0) { 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -0.0; 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ceil(x); 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic Mutex* limit_mutex = NULL; 7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Setup() { 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Seed the random number generator. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the current time to a 64-bit integer first, before converting it 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to an unsigned. Going directly can cause an overflow and the seed to be 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set to all ones. The seed will be identical for different instances that 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // call this setup code within the same millisecond. 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block srandom(static_cast<unsigned int>(seed)); 8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block limit_mutex = CreateMutex(); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 937f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __asm__ __volatile__("" : : : "memory"); 957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch *ptr = value; 967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 987f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 99d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; // FreeBSD runs on anything. 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::ActivationFrameAlignment() { 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 16 byte alignment on FreeBSD 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 16; 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 111d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return t->tm_zone; 116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = time(NULL); 121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // tm_gmtoff includes any daylight savings offset, so subtract it. 123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>(t->tm_gmtoff * msPerSecond - 124d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 125d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 126d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 127d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We keep the lowest and highest addresses mapped as a quick way of 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// determining that pointers are outside the heap (used mostly in assertions 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// and verification). The estimate is conservative, ie, not all addresses in 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 'allocated' space are actually allocated to our heap. The range is 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(limit_mutex != NULL); 13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(limit_mutex); 14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block highest_ever_allocated = 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Max(highest_ever_allocated, 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool OS::IsOutsideAllocatedSpace(void* address) { 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return address < lowest_ever_allocated || address >= highest_ever_allocated; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocksize_t OS::AllocateAlignment() { 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return getpagesize(); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* OS::Allocate(const size_t requested, 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_t* allocated, 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool executable) { 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const size_t msize = RoundUp(requested, getpagesize()); 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mbase == MAP_FAILED) { 16644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *allocated = msize; 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocatedSpaceLimits(mbase, msize); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mbase; 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Free(void* buf, const size_t length) { 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1240712): munmap has a return value which is ignored here. 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = munmap(buf, length); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_HEAP_PROTECTION 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Protect(void* address, size_t size) { 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Unprotect(void* address, size_t size, bool is_executable) { 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNIMPLEMENTED(); 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Sleep(int milliseconds) { 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned int ms = static_cast<unsigned int>(milliseconds); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block usleep(1000 * ms); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Abort() { 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Redirect to std abort to signal abnormal program termination. 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block abort(); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::DebugBreak() { 210756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#if (defined(__arm__) || defined(__thumb__)) 211756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# if defined(CAN_USE_ARMV5_INSTRUCTIONS) 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("bkpt 0"); 213756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# endif 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block asm("int $3"); 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PosixMemoryMappedFile(FILE* file, void* memory, int size) 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : file_(file), memory_(memory), size_(size) { } 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~PosixMemoryMappedFile(); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void* memory() { return memory_; } 2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file_; 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory_; 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int size_; 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* initial) { 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* file = fopen(name, "w+"); 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file == NULL) return NULL; 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = fwrite(initial, size, 1, file); 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) { 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory = 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new PosixMemoryMappedFile(file, memory, size); 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockPosixMemoryMappedFile::~PosixMemoryMappedFile() { 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (memory_) munmap(memory_, size_); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block fclose(file_); 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_LOGGING_AND_PROFILING 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic unsigned StringToLong(char* buffer) { 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::LogSharedLibraryAddresses() { 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_LOGGING_AND_PROFILING 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int MAP_LENGTH = 1024; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int fd = open("/proc/self/maps", O_RDONLY); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fd < 0) return; 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char addr_buffer[11]; 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[0] = '0'; 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[1] = 'x'; 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr_buffer[10] = 0; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = read(fd, addr_buffer + 2, 8); 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 8) break; 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned start = StringToLong(addr_buffer); 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, addr_buffer + 2, 1); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) break; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (addr_buffer[2] != '-') break; 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, addr_buffer + 2, 8); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 8) break; 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block unsigned end = StringToLong(addr_buffer); 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char buffer[MAP_LENGTH]; 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int bytes_read = -1; 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block do { 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bytes_read++; 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (bytes_read >= MAP_LENGTH - 1) 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = read(fd, buffer + bytes_read, 1); 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result < 1) break; 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } while (buffer[bytes_read] != '\n'); 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[bytes_read] = 0; 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ignore mappings that are not executable. 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (buffer[3] != 'x') continue; 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* start_of_path = index(buffer, '/'); 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // There may be no filename in this line. Skip to next. 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_of_path == NULL) continue; 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer[bytes_read] = 0; 31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end)); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block close(fd); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 318f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 319f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 320f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frames_size = frames.length(); 32325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ScopedVector<void*> addresses(frames_size); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen int frames_count = backtrace(addresses.start(), frames_size); 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke char** symbols = backtrace_symbols(addresses.start(), frames_count); 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (symbols == NULL) { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kStackWalkError; 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < frames_count; i++) { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].address = addresses[i]; 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Format a text representation of the frame based on the information 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // available. 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen), 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s", 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbols[i]); 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure line termination is in place. 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block free(symbols); 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return frames_count; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Constants used for mmap. 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFd = -1; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const int kMmapFdOffset = 0; 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::VirtualMemory(size_t size) { 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block address_ = mmap(NULL, size, PROT_NONE, 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kMmapFd, kMmapFdOffset); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block size_ = size; 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockVirtualMemory::~VirtualMemory() { 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsReserved()) { 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (0 == munmap(address(), size())) address_ = MAP_FAILED; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::IsReserved() { 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return address_ != MAP_FAILED; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::Commit(void* address, size_t size, bool executable) { 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (MAP_FAILED == mmap(address, size, prot, 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_FIXED, 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kMmapFd, kMmapFdOffset)) { 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UpdateAllocatedSpaceLimits(address, size); 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool VirtualMemory::Uncommit(void* address, size_t size) { 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mmap(address, size, PROT_NONE, 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kMmapFd, kMmapFdOffset) != MAP_FAILED; 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_t thread_; // Thread handle for pthread. 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThreadHandle::ThreadHandle(Kind kind) { 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data_ = new PlatformData(kind); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadHandle::Initialize(ThreadHandle::Kind kind) { 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data_->Initialize(kind); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThreadHandle::~ThreadHandle() { 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ThreadHandle::IsSelf() const { 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pthread_equal(data_->thread_, pthread_self()); 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ThreadHandle::IsValid() const { 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return data_->thread_ != kNoThread; 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThread::Thread(Isolate* isolate, const Options& options) 4268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatformData), 42744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_(isolate), 42844f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_size_(options.stack_size) { 42944f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_name(options.name); 4309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 4319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 4329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 43344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThread::Thread(Isolate* isolate, const char* name) 4348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatformData), 43544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_(isolate), 43644f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_size_(0) { 4371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block set_name(name); 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::~Thread() { 4428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* ThreadEntry(void* arg) { 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Thread* thread = reinterpret_cast<Thread*>(arg); 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This is also initialized by the first argument to pthread_create() but we 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // don't know which thread will run first (the original thread or the new 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // one) so we initialize it here too. 4518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread_->data_->thread_ = pthread_self(); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(thread->IsValid()); 45344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate()); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread->Run(); 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 4609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 4619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 4629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 4639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 4649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Start() { 46644f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 46744f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_create(&thread_handle_data()->thread_, attr_ptr, ThreadEntry, this); 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsValid()); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Join() { 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_join(thread_handle_data()->thread_, NULL); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t key; 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_create(&key, NULL); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<LocalStorageKey>(key); 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_key_delete(pthread_key); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return pthread_getspecific(pthread_key); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_setspecific(pthread_key, value); 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::YieldCPU() { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sched_yield(); 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FreeBSDMutex : public Mutex { 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FreeBSDMutex() { 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutexattr_t attrs; 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutexattr_init(&attrs); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = pthread_mutex_init(&mutex_, &attrs); 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result == 0); 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~FreeBSDMutex() { pthread_mutex_destroy(&mutex_); } 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual int Lock() { 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutex_lock(&mutex_); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual int Unlock() { 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = pthread_mutex_unlock(&mutex_); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54244f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual bool TryLock() { 54344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = pthread_mutex_trylock(&mutex_); 54444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return false if the lock is busy and locking failed. 54544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result == EBUSY) { 54644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return false; 54744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0); // Verify no other errors. 54944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 55144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMutex* OS::CreateMutex() { 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new FreeBSDMutex(); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass FreeBSDSemaphore : public Semaphore { 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit FreeBSDSemaphore(int count) { sem_init(&sem_, 0, count); } 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); } 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void Wait(); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual bool Wait(int timeout); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void Signal() { sem_post(&sem_); } 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sem_t sem_; 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid FreeBSDSemaphore::Wait() { 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = sem_wait(&sem_); 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == 0) return; // Successfully got semaphore. 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool FreeBSDSemaphore::Wait(int timeout) { 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const long kOneSecondMicros = 1000000; // NOLINT 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Split timeout into second and nanosecond parts. 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval delta; 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta.tv_usec = timeout % kOneSecondMicros; 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delta.tv_sec = timeout / kOneSecondMicros; 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval current_time; 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the current time. 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (gettimeofday(¤t_time, NULL) == -1) { 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate time for end of timeout. 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timeval end_time; 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block timeradd(¤t_time, &delta, &end_time); 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct timespec ts; 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TIMEVAL_TO_TIMESPEC(&end_time, &ts); 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (true) { 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = sem_timedwait(&sem_, &ts); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == 0) return true; // Successfully got semaphore. 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSemaphore* OS::CreateSemaphore(int count) { 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new FreeBSDSemaphore(count); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_LOGGING_AND_PROFILING 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 62044f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic pthread_t GetThreadID() { 62144f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t thread_id = pthread_self(); 62244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return thread_id; 62344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 62444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 62544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 62644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Sampler::PlatformData : public Malloced { 62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 62844f0eee88ff00398ff7f715fab053374d808c90dSteve Block PlatformData() : vm_tid_(GetThreadID()) {} 62944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t vm_tid() const { return vm_tid_; } 63144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 63244f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 63344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_t vm_tid_; 63444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 63544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(info); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (signal != SIGPROF) return; 64044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = Isolate::UncheckedCurrent(); 64144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 64244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We require a fully initialized and entered isolate. 64344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 64444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 6458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (v8::Locker::IsActive() && 6468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch !isolate->thread_manager()->IsLockedByCurrentThread()) { 6478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 6488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 65044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sampler* sampler = isolate->logger()->sampler(); 65144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sampler == NULL || !sampler->IsActive()) return; 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 65344f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample sample_obj; 65444f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 65544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sample == NULL) sample = &sample_obj; 6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 65744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Extracting the sample from the context is extremely machine dependent. 65844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 65944f0eee88ff00398ff7f715fab053374d808c90dSteve Block mcontext_t& mcontext = ucontext->uc_mcontext; 66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->state = isolate->current_vm_state(); 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_HOST_ARCH_IA32 66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); 66344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); 66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_X64 66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); 66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); 66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_HOST_ARCH_ARM 67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); 67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); 67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 67444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->SampleStack(sample); 67544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->Tick(sample); 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 67944f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SignalSender : public Thread { 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 68144f0eee88ff00398ff7f715fab053374d808c90dSteve Block enum SleepInterval { 68244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HALF_INTERVAL, 68344f0eee88ff00398ff7f715fab053374d808c90dSteve Block FULL_INTERVAL 68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit SignalSender(int interval) 68744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : Thread(NULL, "SignalSender"), 68844f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval) {} 68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void AddActiveSampler(Sampler* sampler) { 69144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(mutex_); 69244f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::AddActiveSampler(sampler); 69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instance_ == NULL) { 69444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Install a signal handler. 69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block struct sigaction sa; 69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa.sa_sigaction = ProfilerSignalHandler; 69744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sigemptyset(&sa.sa_mask); 69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sa.sa_flags = SA_RESTART | SA_SIGINFO; 69944f0eee88ff00398ff7f715fab053374d808c90dSteve Block signal_handler_installed_ = 70044f0eee88ff00398ff7f715fab053374d808c90dSteve Block (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 70144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 70244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Start a thread that sends SIGPROF signal to VM threads. 70344f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = new SignalSender(sampler->interval()); 70444f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_->Start(); 70544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 70644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instance_->interval_ == sampler->interval()); 70744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 71044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void RemoveActiveSampler(Sampler* sampler) { 71144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(mutex_); 71244f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::RemoveActiveSampler(sampler); 71344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 71444f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown(); 71544f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_->Join(); 71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete instance_; 71744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = NULL; 71844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Restore the old signal handler. 72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (signal_handler_installed_) { 72144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sigaction(SIGPROF, &old_signal_handler_, 0); 72244f0eee88ff00398ff7f715fab053374d808c90dSteve Block signal_handler_installed_ = false; 72344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 72444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 72544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 72644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Implement Thread::Run(). 72844f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Run() { 72944f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::State state; 73044f0eee88ff00398ff7f715fab053374d808c90dSteve Block while ((state = SamplerRegistry::GetState()) != 73144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::HAS_NO_SAMPLERS) { 73244f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool cpu_profiling_enabled = 73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 73444f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 73544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // When CPU profiling is enabled both JavaScript and C++ code is 73644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // profiled. We must not suspend. 73744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!cpu_profiling_enabled) { 73844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rate_limiter_.SuspendIfNecessary()) continue; 73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 74044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled && runtime_profiler_enabled) { 74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 74344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 74444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 74544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 74644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 74744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 74844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 74944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled) { 75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block this)) { 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 75644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (runtime_profiler_enabled) { 75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, 75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block NULL)) { 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(FULL_INTERVAL); 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->IsProfiling()) return; 76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 77444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 77544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->isolate()->runtime_profiler()->NotifyTick(); 77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SendProfilingSignal(pthread_t tid) { 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!signal_handler_installed_) return; 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_kill(tid, SIGPROF); 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Sleep(SleepInterval full_or_half) { 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert ms to us and subtract 100 us to compensate delays 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // occuring during signal delivery. 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block useconds_t interval = interval_ * 1000 - 100; 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (full_or_half == HALF_INTERVAL) interval /= 2; 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = usleep(interval); 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result != 0 && errno != EINTR) { 79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block fprintf(stderr, 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block "SignalSender usleep error; interval = %u, errno = %d\n", 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval, 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block errno); 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0 || errno == EINTR); 79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block USE(result); 79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 80144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int interval_; 80244f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfilerRateLimiter rate_limiter_; 80344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Protects the process wide state below. 80544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static Mutex* mutex_; 80644f0eee88ff00398ff7f715fab053374d808c90dSteve Block static SignalSender* instance_; 80744f0eee88ff00398ff7f715fab053374d808c90dSteve Block static bool signal_handler_installed_; 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static struct sigaction old_signal_handler_; 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(SignalSender); 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 81344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockMutex* SignalSender::mutex_ = OS::CreateMutex(); 81444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSignalSender* SignalSender::instance_ = NULL; 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstruct sigaction SignalSender::old_signal_handler_; 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool SignalSender::signal_handler_installed_ = false; 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 8238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 8248a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block data_ = new PlatformData; 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSampler::~Sampler() { 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Start() { 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(true); 83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender::AddActiveSampler(this); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Stop() { 84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsActive()); 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block SignalSender::RemoveActiveSampler(this); 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(false); 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // ENABLE_LOGGING_AND_PROFILING 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 851