13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Redistribution and use in source and binary forms, with or without 3d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modification, are permitted provided that the following conditions are 4d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// met: 5d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// 6d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// * Redistributions of source code must retain the above copyright 7d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// notice, this list of conditions and the following disclaimer. 8d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// * Redistributions in binary form must reproduce the above 9d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// copyright notice, this list of conditions and the following 10d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// disclaimer in the documentation and/or other materials provided 11d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// with the distribution. 12d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// * Neither the name of Google Inc. nor the names of its 13d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// contributors may be used to endorse or promote products derived 14d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// from this software without specific prior written permission. 15d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// 16d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 28d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Platform specific code for Solaris 10 goes here. For the POSIX comaptible 29d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// parts the implementation is in platform-posix.cc. 30d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 31d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifdef __sparc 32d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke# error "V8 does not support the SPARC CPU architecture." 33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif 34d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sys/stack.h> // for stack alignment 36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <unistd.h> // getpagesize(), usleep() 37d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sys/mman.h> // mmap() 38f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include <ucontext.h> // walkstack(), getcontext() 39f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include <dlfcn.h> // dladdr 40d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <pthread.h> 41d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sched.h> // for sched_yield 42d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <semaphore.h> 43d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <time.h> 44d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sys/time.h> // gettimeofday(), timeradd() 45d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <errno.h> 46d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <ieeefp.h> // finite() 47d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <signal.h> // sigemptyset(), etc 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include <sys/regset.h> 49d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 50d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 51d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#undef MAP_TYPE 52d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 53d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "v8.h" 54d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "platform-posix.h" 56d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "platform.h" 573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8threads.h" 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 59d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 60d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 61f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// It seems there is a bug in some Solaris distributions (experienced in 62f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// SunOS 5.10 Generic_141445-09) which make it difficult or impossible to 63f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// access signbit() despite the availability of other C99 math functions. 64f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifndef signbit 65f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Test sign - usually defined in math.h 66f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeint signbit(double x) { 67f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We need to take care of the special case of both positive and negative 68f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // versions of zero. 69f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (x == 0) { 70f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return fpclass(x) & FP_NZERO; 71f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 72f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // This won't detect negative NaN but that should be okay since we don't 73f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // assume that behavior. 74f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return x < 0; 75f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 76f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 77f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // signbit 78f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 79d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace v8 { 80d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace internal { 81d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 82d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 83d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// 0 is never a valid thread id on Solaris since the main thread is 1 and 84d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// subsequent have their ids incremented from there 85d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic const pthread_t kNoThread = (pthread_t) 0; 86d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 87d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 88d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble ceiling(double x) { 89d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return ceil(x); 90d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 91d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 92d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Mutex* limit_mutex = NULL; 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() { 95d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Seed the random number generator. 96d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Convert the current time to a 64-bit integer first, before converting it 97d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // to an unsigned. Going directly will cause an overflow and the seed to be 98d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // set to all ones. The seed will be identical for different instances that 99d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // call this setup code within the same millisecond. 100d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 101d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke srandom(static_cast<unsigned int>(seed)); 1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch limit_mutex = CreateMutex(); 103d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 104d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 105d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() { 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math functions depend on CPU features therefore they are initialized after 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CPU. 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathSetup(); 1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeuint64_t OS::CpuFeaturesImpliedByPlatform() { 114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return 0; // Solaris runs on a lot of things. 115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint OS::ActivationFrameAlignment() { 1197d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // GCC generates code that requires 16 byte alignment such as movdqa. 1207d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch return Max(STACK_ALIGN, 16); 121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 1247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 1257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch __asm__ __volatile__("" : : : "memory"); 1267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch *ptr = value; 1277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 1287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 1297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return tzname[0]; // The location of the timezone string on Solaris. 136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // On Solaris, struct tm does not contain a tm_gmtoff field. 141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t utc = time(NULL); 142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(utc != -1); 143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* loc = localtime(&utc); 144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(loc != NULL); 145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>((mktime(loc) - utc) * msPerSecond); 146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 148d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// We keep the lowest and highest addresses mapped as a quick way of 150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// determining that pointers are outside the heap (used mostly in assertions 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification). The estimate is conservative, i.e., not all addresses in 152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// 'allocated' space are actually allocated to our heap. The range is 153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// [lowest, highest), inclusive on the low and and exclusive on the high end. 154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void UpdateAllocatedSpaceLimits(void* address, int size) { 1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(limit_mutex != NULL); 1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ScopedLock lock(limit_mutex); 1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 162d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke lowest_ever_allocated = Min(lowest_ever_allocated, address); 163d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke highest_ever_allocated = 164d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Max(highest_ever_allocated, 165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 166d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 167d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 168d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkebool OS::IsOutsideAllocatedSpace(void* address) { 170d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return address < lowest_ever_allocated || address >= highest_ever_allocated; 171d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 173d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkesize_t OS::AllocateAlignment() { 175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<size_t>(getpagesize()); 176d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 179d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid* OS::Allocate(const size_t requested, 180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke size_t* allocated, 181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke bool is_executable) { 182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const size_t msize = RoundUp(requested, getpagesize()); 183d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 185d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 186d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (mbase == MAP_FAILED) { 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 188d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return NULL; 189d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke *allocated = msize; 191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke UpdateAllocatedSpaceLimits(mbase, msize); 192d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return mbase; 193d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 194d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 195d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 196d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::Free(void* address, const size_t size) { 197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // TODO(1240712): munmap has a return value which is ignored here. 198d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int result = munmap(address, size); 199d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke USE(result); 200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(result == 0); 201d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 202d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 203d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 204d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::Sleep(int milliseconds) { 205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke useconds_t ms = static_cast<useconds_t>(milliseconds); 206d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke usleep(1000 * ms); 207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::Abort() { 211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Redirect to std abort to signal abnormal program termination. 212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke abort(); 213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::DebugBreak() { 217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke asm("int $3"); 218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke PosixMemoryMappedFile(FILE* file, void* memory, int size) 224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke : file_(file), memory_(memory), size_(size) { } 225d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual ~PosixMemoryMappedFile(); 226d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void* memory() { return memory_; } 2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private: 229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke FILE* file_; 230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void* memory_; 231d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int size_; 232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 233d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 249d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void* initial) { 250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke FILE* file = fopen(name, "w+"); 251d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (file == NULL) return NULL; 252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int result = fwrite(initial, size, 1, file); 253d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (result < 1) { 254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke fclose(file); 255d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return NULL; 256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke void* memory = 258d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 259d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return new PosixMemoryMappedFile(file, memory, size); 260d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 261d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 262d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 263d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkePosixMemoryMappedFile::~PosixMemoryMappedFile() { 264d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (memory_) munmap(memory_, size_); 265d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke fclose(file_); 266d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 267d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 269d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::LogSharedLibraryAddresses() { 270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 272d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 273f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 274f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 275f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 276f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestruct StackWalker { 278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Vector<OS::StackFrame>& frames; 279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int index; 280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}; 281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic int StackWalkCallback(uintptr_t pc, int signo, void* data) { 284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke struct StackWalker* walker = static_cast<struct StackWalker*>(data); 285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Dl_info info; 286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke int i = walker->index; 288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke walker->frames[i].address = reinterpret_cast<void*>(pc); 290d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Make sure line termination is in place. 292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke walker->frames[i].text[OS::kStackWalkMaxTextLen - 1] = '\0'; 293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke Vector<char> text = MutableCStrVector(walker->frames[i].text, 295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke OS::kStackWalkMaxTextLen); 296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (dladdr(reinterpret_cast<void*>(pc), &info) == 0) { 298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke OS::SNPrintF(text, "[0x%p]", pc); 299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else if ((info.dli_fname != NULL && info.dli_sname != NULL)) { 300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // We have symbol info. 301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke OS::SNPrintF(text, "%s'%s+0x%x", info.dli_fname, info.dli_sname, pc); 302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } else { 303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // No local symbol info. 304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke OS::SNPrintF(text, 305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke "%s'0x%p [0x%p]", 306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke info.dli_fname, 307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke pc - reinterpret_cast<uintptr_t>(info.dli_fbase), 308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke pc); 309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke walker->index++; 311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return 0; 312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 314d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeint OS::StackWalk(Vector<OS::StackFrame> frames) { 316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ucontext_t ctx; 317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke struct StackWalker walker = { frames, 0 }; 318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (getcontext(&ctx) < 0) return kStackWalkError; 320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke if (!walkcontext(&ctx, StackWalkCallback, &walker)) { 322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return kStackWalkError; 323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke } 324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke return walker.index; 326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 328d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Constants used for mmap. 330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic const int kMmapFd = -1; 331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic const int kMmapFdOffset = 0; 332d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 333d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeVirtualMemory::VirtualMemory(size_t size) { 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = ReserveRegion(size); 338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke size_ = size; 339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 341d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(NULL), size_(0) { 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t request_size = RoundUp(size + alignment, 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* reservation = mmap(OS::GetRandomMmapAddr(), 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size, 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (reservation == MAP_FAILED) return; 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address base = static_cast<Address>(reservation); 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address aligned_base = RoundUp(base, alignment); 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(base, aligned_base); 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Unmap extra memory reserved before and after the desired block. 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_base != base) { 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t prefix_size = static_cast<size_t>(aligned_base - base); 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(base, prefix_size); 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= prefix_size; 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_LE(aligned_size, request_size); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (aligned_size != request_size) { 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t suffix_size = request_size - aligned_size; 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Free(aligned_base + aligned_size, suffix_size); 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size -= suffix_size; 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(aligned_size == request_size); 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = static_cast<void*>(aligned_base); 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = aligned_size; 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeVirtualMemory::~VirtualMemory() { 383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (IsReserved()) { 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result = ReleaseRegion(address(), size()); 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(result); 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 387d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 388d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 391d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkebool VirtualMemory::IsReserved() { 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return address_ != NULL; 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid VirtualMemory::Reset() { 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = NULL; 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = 0; 399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return CommitRegion(address, size, is_executable); 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return UncommitRegion(address, size); 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) { 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::Guard(address, OS::CommitPageSize()); 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* result = mmap(OS::GetRandomMmapAddr(), 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset); 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (result == MAP_FAILED) return NULL; 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return result; 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (MAP_FAILED == mmap(base, 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prot, 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset)) { 440d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return false; 441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 442d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UpdateAllocatedSpaceLimits(base, size); 444d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return true; 445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 446d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) { 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return mmap(base, 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size, 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PROT_NONE, 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFd, 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kMmapFdOffset) != MAP_FAILED; 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return munmap(base, size) == 0; 460d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 461d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 462d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 4638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 464d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 4658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PlatformData() : thread_(kNoThread) { } 466d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 467d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_t thread_; // Thread handle for pthread. 468d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 469d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 47085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochThread::Thread(const Options& options) 47285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch : data_(new PlatformData()), 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stack_size_(options.stack_size()) { 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_name(options.name()); 475d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 476d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 477d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 478d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeThread::~Thread() { 4798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 482d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void* ThreadEntry(void* arg) { 484d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke Thread* thread = reinterpret_cast<Thread*>(arg); 485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // This is also initialized by the first argument to pthread_create() but we 486d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // don't know which thread will run first (the original thread or the new 487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // one) so we initialize it here too. 4888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread->data()->thread_ = pthread_self(); 4898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke thread->Run(); 491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return NULL; 492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 4959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 4969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 4979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 4989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 4999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::Start() { 50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_create(&data_->thread_, NULL, ThreadEntry, this); 5108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(data_->thread_ != kNoThread); 511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 513d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 514d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::Join() { 5158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_join(data_->thread_, NULL); 516d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 517d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 518d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 519d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeThread::LocalStorageKey Thread::CreateThreadLocalKey() { 520d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_key_t key; 521d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int result = pthread_key_create(&key, NULL); 522d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke USE(result); 523d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(result == 0); 524d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<LocalStorageKey>(key); 525d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 526d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 527d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int result = pthread_key_delete(pthread_key); 531d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke USE(result); 532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT(result == 0); 533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 535d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid* Thread::GetThreadLocal(LocalStorageKey key) { 537d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return pthread_getspecific(pthread_key); 539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_setspecific(pthread_key, value); 545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::YieldCPU() { 549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke sched_yield(); 550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SolarisMutex : public Mutex { 554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 555d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke SolarisMutex() { 556d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_mutexattr_t attr; 557d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_mutexattr_init(&attr); 558d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 559d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_mutex_init(&mutex_, &attr); 560d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ~SolarisMutex() { pthread_mutex_destroy(&mutex_); } 563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 564d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int Lock() { return pthread_mutex_lock(&mutex_); } 565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int Unlock() { return pthread_mutex_unlock(&mutex_); } 567d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch virtual bool TryLock() { 569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch int result = pthread_mutex_trylock(&mutex_); 570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Return false if the lock is busy and locking failed. 571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (result == EBUSY) { 572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return false; 573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 574b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(result == 0); // Verify no other errors. 575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return true; 576b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private: 579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke pthread_mutex_t mutex_; 580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMutex* OS::CreateMutex() { 584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return new SolarisMutex(); 585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 587d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SolarisSemaphore : public Semaphore { 589d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke explicit SolarisSemaphore(int count) { sem_init(&sem_, 0, count); } 591d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual ~SolarisSemaphore() { sem_destroy(&sem_); } 592d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 593d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void Wait(); 594d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual bool Wait(int timeout); 595d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke virtual void Signal() { sem_post(&sem_); } 596d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private: 597d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke sem_t sem_; 598d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}; 599d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 601d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid SolarisSemaphore::Wait() { 602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke while (true) { 603d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int result = sem_wait(&sem_); 604d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (result == 0) return; // Successfully got semaphore. 605d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 606d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 607d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 609d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 610d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifndef TIMEVAL_TO_TIMESPEC 611d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ 612d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (ts)->tv_sec = (tv)->tv_sec; \ 613d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (ts)->tv_nsec = (tv)->tv_usec * 1000; \ 614d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} while (false) 615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif 616d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 617d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifndef timeradd 619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define timeradd(a, b, result) \ 620d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke do { \ 621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ 622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ 623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if ((result)->tv_usec >= 1000000) { \ 624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ++(result)->tv_sec; \ 625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (result)->tv_usec -= 1000000; \ 626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } \ 627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } while (0) 628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif 629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkebool SolarisSemaphore::Wait(int timeout) { 632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke const long kOneSecondMicros = 1000000; // NOLINT 633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Split timeout into second and nanosecond parts. 635d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct timeval delta; 636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke delta.tv_usec = timeout % kOneSecondMicros; 637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke delta.tv_sec = timeout / kOneSecondMicros; 638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct timeval current_time; 640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Get the current time. 641d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (gettimeofday(¤t_time, NULL) == -1) { 642d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return false; 643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 645d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Calculate time for end of timeout. 646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct timeval end_time; 647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke timeradd(¤t_time, &delta, &end_time); 648d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 649d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct timespec ts; 650d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke TIMEVAL_TO_TIMESPEC(&end_time, &ts); 651d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // Wait for semaphore signalled or timeout. 652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke while (true) { 653d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke int result = sem_timedwait(&sem_, &ts); 654d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (result == 0) return true; // Successfully got semaphore. 655d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 656d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 657d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 658d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 659d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 660d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 661d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeSemaphore* OS::CreateSemaphore(int count) { 662d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return new SolarisSemaphore(count); 663d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 664d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 665d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 66644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic pthread_t GetThreadID() { 66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block return pthread_self(); 66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 670d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 671d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke USE(info); 672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (signal != SIGPROF) return; 6733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 6743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 6753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // We require a fully initialized and entered isolate. 6763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 6773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (v8::Locker::IsActive() && 6793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch !isolate->thread_manager()->IsLockedByCurrentThread()) { 6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 6813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Sampler* sampler = isolate->logger()->sampler(); 6843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (sampler == NULL || !sampler->IsActive()) return; 685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch TickSample sample_obj; 6873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (sample == NULL) sample = &sample_obj; 689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Extracting the sample from the context is extremely machine dependent. 691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch mcontext_t& mcontext = ucontext->uc_mcontext; 6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sample->state = isolate->current_vm_state(); 694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]); 69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]); 69744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]); 69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sampler->SampleStack(sample); 7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sampler->Tick(sample); 701d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass Sampler::PlatformData : public Malloced { 704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public: 7053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PlatformData() : vm_tid_(GetThreadID()) {} 7063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch pthread_t vm_tid() const { return vm_tid_; } 7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch pthread_t vm_tid_; 7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}; 7123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass SignalSender : public Thread { 7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block enum SleepInterval { 7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HALF_INTERVAL, 7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FULL_INTERVAL 71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block }; 72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSignalSenderStackSize = 64 * KB; 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch explicit SignalSender(int interval) 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), 7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch interval_(interval) {} 7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void InstallSignalHandler() { 7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch struct sigaction sa; 7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sa.sa_sigaction = ProfilerSignalHandler; 7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sigemptyset(&sa.sa_mask); 7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sa.sa_flags = SA_RESTART | SA_SIGINFO; 7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch signal_handler_installed_ = 7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void RestoreSignalHandler() { 7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (signal_handler_installed_) { 7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sigaction(SIGPROF, &old_signal_handler_, 0); 7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch signal_handler_installed_ = false; 7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void AddActiveSampler(Sampler* sampler) { 7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 7453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::AddActiveSampler(sampler); 7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (instance_ == NULL) { 7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Start a thread that will send SIGPROF signal to VM threads, 7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // when CPU profiling will be enabled. 7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instance_ = new SignalSender(sampler->interval()); 7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instance_->Start(); 7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(instance_->interval_ == sampler->interval()); 7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void RemoveActiveSampler(Sampler* sampler) { 7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 7583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::RemoveActiveSampler(sampler); 7593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 7603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 7613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch delete instance_; 7623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instance_ = NULL; 7633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RestoreSignalHandler(); 7643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 7673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Implement Thread::Run(). 7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch virtual void Run() { 7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::State state; 7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while ((state = SamplerRegistry::GetState()) != 7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SamplerRegistry::HAS_NO_SAMPLERS) { 7723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool cpu_profiling_enabled = 7733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 7743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 7753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (cpu_profiling_enabled && !signal_handler_installed_) { 7763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch InstallSignalHandler(); 7773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (!cpu_profiling_enabled && signal_handler_installed_) { 7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RestoreSignalHandler(); 7793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // When CPU profiling is enabled both JavaScript and C++ code is 7823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // profiled. We must not suspend. 7833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!cpu_profiling_enabled) { 7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (rate_limiter_.SuspendIfNecessary()) continue; 7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (cpu_profiling_enabled && runtime_profiler_enabled) { 7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 7913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 7923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(HALF_INTERVAL); 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (cpu_profiling_enabled) { 7973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, 7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch this)) { 7993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 8003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (runtime_profiler_enabled) { 8033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, 8043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch NULL)) { 8053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return; 8063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Sleep(FULL_INTERVAL); 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 8143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!sampler->IsProfiling()) return; 8153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 8203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!sampler->isolate()->IsInitialized()) return; 8213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sampler->isolate()->runtime_profiler()->NotifyTick(); 8223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void SendProfilingSignal(pthread_t tid) { 82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!signal_handler_installed_) return; 8263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch pthread_kill(tid, SIGPROF); 827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke } 828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block void Sleep(SleepInterval full_or_half) { 83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert ms to us and subtract 100 us to compensate delays 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // occuring during signal delivery. 8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch useconds_t interval = interval_ * 1000 - 100; 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (full_or_half == HALF_INTERVAL) interval /= 2; 83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int result = usleep(interval); 83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG 83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (result != 0 && errno != EINTR) { 83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block fprintf(stderr, 83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block "SignalSender usleep error; interval = %u, errno = %d\n", 83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval, 84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block errno); 84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0 || errno == EINTR); 84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block USE(result); 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch const int interval_; 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfilerRateLimiter rate_limiter_; 849d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 8503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Protects the process wide state below. 8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static LazyMutex mutex_; 8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static SignalSender* instance_; 8533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool signal_handler_installed_; 8543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static struct sigaction old_signal_handler_; 855d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 8573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DISALLOW_COPY_AND_ASSIGN(SignalSender); 8583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}; 8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; 8613fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochSignalSender* SignalSender::instance_ = NULL; 8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstruct sigaction SignalSender::old_signal_handler_; 8633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool SignalSender::signal_handler_installed_ = false; 86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 86644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 8708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 8718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 8723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch data_ = new PlatformData; 873d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 876d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeSampler::~Sampler() { 8773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!IsActive()); 878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke delete data_; 879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Sampler::Start() { 88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 88444f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(true); 8853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SignalSender::AddActiveSampler(this); 886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Sampler::Stop() { 8903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(IsActive()); 8913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch SignalSender::RemoveActiveSampler(this); 89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block SetActive(false); 893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} } // namespace v8::internal 896