1d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Copyright 2006-2009 the V8 project authors. All rights reserved. 2d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Redistribution and use in source and binary forms, with or without 3d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// modification, are permitted provided that the following conditions are 4d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// met: 5d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 6d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// * Redistributions of source code must retain the above copyright 7d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// notice, this list of conditions and the following disclaimer. 8d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// * Redistributions in binary form must reproduce the above 9d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// copyright notice, this list of conditions and the following 10d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// disclaimer in the documentation and/or other materials provided 11d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// with the distribution. 12d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// * Neither the name of Google Inc. nor the names of its 13d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// contributors may be used to endorse or promote products derived 14d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// from this software without specific prior written permission. 15d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 16d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 28d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Platform specific code for OpenBSD goes here. For the POSIX comaptible parts 29d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// the implementation is in platform-posix.cc. 30d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 31d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <pthread.h> 32d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <semaphore.h> 33d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <signal.h> 34d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/time.h> 35d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/resource.h> 36d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/types.h> 37d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <stdlib.h> 38d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 39d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/types.h> // mmap & munmap 40d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/mman.h> // mmap & munmap 41d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/stat.h> // open 42d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <sys/fcntl.h> // open 43d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <unistd.h> // getpagesize 44d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <execinfo.h> // backtrace, backtrace_symbols 45d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <strings.h> // index 46d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <errno.h> 47d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <stdarg.h> 48d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include <limits.h> 49d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 50d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#undef MAP_TYPE 51d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 52d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "v8.h" 53d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 54d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#include "platform.h" 55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 56d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 57d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 58d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blocknamespace v8 { 59d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blocknamespace internal { 60d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 61d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 0 is never a valid thread id on OpenBSD since tids and pids share a 62d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// name space and pid 0 is used to kill the group (see man 2 kill). 63d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const pthread_t kNoThread = (pthread_t) 0; 64d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 65d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 66d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockdouble ceiling(double x) { 67d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Correct as on OS X 68d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (-1.0 < x && x < 0.0) { 69d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return -0.0; 70d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } else { 71d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return ceil(x); 72d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 73d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 74d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 75d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 76d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Setup() { 77d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Seed the random number generator. 78d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Convert the current time to a 64-bit integer first, before converting it 79d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // to an unsigned. Going directly can cause an overflow and the seed to be 80d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // set to all ones. The seed will be identical for different instances that 81d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // call this setup code within the same millisecond. 82d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 83d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block srandom(static_cast<unsigned int>(seed)); 84d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 85d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 86d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 873bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 883bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __asm__ __volatile__("" : : : "memory"); 893bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch *ptr = value; 903bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 913bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 923bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 93d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 94d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; // OpenBSD runs on anything. 95d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 96d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 97d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 98d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint OS::ActivationFrameAlignment() { 99d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // 16 byte alignment on OpenBSD 100d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 16; 101d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 102d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 103d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 104d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) { 105d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (isnan(time)) return ""; 106d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 107d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 108d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke if (NULL == t) return ""; 109d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return t->tm_zone; 110d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 111d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 112d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() { 114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke time_t tv = time(NULL); 115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke struct tm* t = localtime(&tv); 116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke // tm_gmtoff includes any daylight savings offset, so subtract it. 117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke return static_cast<double>(t->tm_gmtoff * msPerSecond - 118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 119d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} 120d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 122d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// We keep the lowest and highest addresses mapped as a quick way of 123d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// determining that pointers are outside the heap (used mostly in assertions 124d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// and verification). The estimate is conservative, ie, not all addresses in 125d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// 'allocated' space are actually allocated to our heap. The range is 126d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 127d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 128d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 129d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 130d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 131d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 132d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 133d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block highest_ever_allocated = 134d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Max(highest_ever_allocated, 135d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 136d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 137d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 138d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 139d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool OS::IsOutsideAllocatedSpace(void* address) { 140d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return address < lowest_ever_allocated || address >= highest_ever_allocated; 141d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 142d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 143d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 144d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blocksize_t OS::AllocateAlignment() { 145d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return getpagesize(); 146d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 147d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 148d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 149d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid* OS::Allocate(const size_t requested, 150d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block size_t* allocated, 151d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool executable) { 152d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const size_t msize = RoundUp(requested, getpagesize()); 153d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); 154d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 155d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 156d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (mbase == MAP_FAILED) { 15744f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 158d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return NULL; 159d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 160d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block *allocated = msize; 161d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UpdateAllocatedSpaceLimits(mbase, msize); 162d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return mbase; 163d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 164d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 165d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 166d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Free(void* buf, const size_t length) { 167d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = munmap(buf, length); 168d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(result); 169d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 170d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 171d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 172d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 173d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_HEAP_PROTECTION 174d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 175d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Protect(void* address, size_t size) { 176d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNIMPLEMENTED(); 177d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 178d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 179d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 180d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Unprotect(void* address, size_t size, bool is_executable) { 181d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNIMPLEMENTED(); 182d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 183d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 184d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 185d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 186d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 187d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Sleep(int milliseconds) { 188d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned int ms = static_cast<unsigned int>(milliseconds); 189d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block usleep(1000 * ms); 190d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 191d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 192d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 193d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::Abort() { 194d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Redirect to std abort to signal abnormal program termination. 195d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block abort(); 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 197d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 198d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 199d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::DebugBreak() { 200756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick#if (defined(__arm__) || defined(__thumb__)) 201756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# if defined(CAN_USE_ARMV5_INSTRUCTIONS) 202d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block asm("bkpt 0"); 203756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick# endif 204d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#else 205d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block asm("int $3"); 206d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 207d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 209d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 210d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 212d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PosixMemoryMappedFile(FILE* file, void* memory, int size) 213d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block : file_(file), memory_(memory), size_(size) { } 214d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~PosixMemoryMappedFile(); 215d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void* memory() { return memory_; } 2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 217d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 218d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FILE* file_; 219d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* memory_; 220d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int size_; 221d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 222d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 223d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file == NULL) return NULL; 2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fseek(file, 0, SEEK_END); 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = ftell(file); 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = 2321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new PosixMemoryMappedFile(file, memory, size); 2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 237d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 238d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* initial) { 239d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block FILE* file = fopen(name, "w+"); 240d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (file == NULL) return NULL; 241d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = fwrite(initial, size, 1, file); 242d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result < 1) { 243d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block fclose(file); 244d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return NULL; 245d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 246d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block void* memory = 247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 248d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new PosixMemoryMappedFile(file, memory, size); 249d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 250d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 251d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 252d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockPosixMemoryMappedFile::~PosixMemoryMappedFile() { 253d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (memory_) munmap(memory_, size_); 254d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block fclose(file_); 255d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 256d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 257d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 258d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_LOGGING_AND_PROFILING 259d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic unsigned StringToLong(char* buffer) { 260d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT 261d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 262d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 263d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 264d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 265d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OS::LogSharedLibraryAddresses() { 266d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_LOGGING_AND_PROFILING 267d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const int MAP_LENGTH = 1024; 268d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int fd = open("/proc/self/maps", O_RDONLY); 269d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (fd < 0) return; 270d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block while (true) { 271d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block char addr_buffer[11]; 272d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block addr_buffer[0] = '0'; 273d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block addr_buffer[1] = 'x'; 274d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block addr_buffer[10] = 0; 275d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = read(fd, addr_buffer + 2, 8); 276d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result < 8) break; 277d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned start = StringToLong(addr_buffer); 278d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = read(fd, addr_buffer + 2, 1); 279d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result < 1) break; 280d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (addr_buffer[2] != '-') break; 281d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = read(fd, addr_buffer + 2, 8); 282d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result < 8) break; 283d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block unsigned end = StringToLong(addr_buffer); 284d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block char buffer[MAP_LENGTH]; 285d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int bytes_read = -1; 286d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block do { 287d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bytes_read++; 288d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (bytes_read >= MAP_LENGTH - 1) 289d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block break; 290d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = read(fd, buffer + bytes_read, 1); 291d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result < 1) break; 292d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } while (buffer[bytes_read] != '\n'); 293d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block buffer[bytes_read] = 0; 294d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Ignore mappings that are not executable. 295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (buffer[3] != 'x') continue; 296d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block char* start_of_path = index(buffer, '/'); 297d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // There may be no filename in this line. Skip to next. 298d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (start_of_path == NULL) continue; 299d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block buffer[bytes_read] = 0; 300d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block LOG(SharedLibraryEvent(start_of_path, start, end)); 301d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 302d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block close(fd); 303d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif 304d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 305d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 306d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 307f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 308f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 309f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 310f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 311d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { 312d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UNIMPLEMENTED(); 313d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 1; 314d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 315d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 316d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 317d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block// Constants used for mmap. 318d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const int kMmapFd = -1; 319d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic const int kMmapFdOffset = 0; 320d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 321d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 322d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockVirtualMemory::VirtualMemory(size_t size) { 323d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block address_ = mmap(NULL, size, PROT_NONE, 324d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kMmapFd, kMmapFdOffset); 326d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block size_ = size; 327d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 330d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockVirtualMemory::~VirtualMemory() { 331d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (IsReserved()) { 332d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (0 == munmap(address(), size())) address_ = MAP_FAILED; 333d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 334d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 335d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 336d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool VirtualMemory::IsReserved() { 338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return address_ != MAP_FAILED; 339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 340d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool VirtualMemory::Commit(void* address, size_t size, bool executable) { 343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); 344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (MAP_FAILED == mmap(address, size, prot, 345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block MAP_PRIVATE | MAP_ANON | MAP_FIXED, 346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kMmapFd, kMmapFdOffset)) { 347d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return false; 348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 349d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UpdateAllocatedSpaceLimits(address, size); 351d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return true; 352d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 353d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 354d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 355d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool VirtualMemory::Uncommit(void* address, size_t size) { 356d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return mmap(address, size, PROT_NONE, 357d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 358d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block kMmapFd, kMmapFdOffset) != MAP_FAILED; 359d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 360d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 361d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 3628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 363d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 3648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PlatformData() : thread_(kNoThread) {} 365d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 366d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_t thread_; // Thread handle for pthread. 367d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 368d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 37044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThread::Thread(Isolate* isolate, const Options& options) 3718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatformData()), 37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_(isolate), 37344f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_size_(options.stack_size) { 37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_name(options.name); 3759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 3769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 37844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThread::Thread(Isolate* isolate, const char* name) 3798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : data_(new PlatfromData()), 38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_(isolate), 38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block stack_size_(0) { 3829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block set_name(name); 383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 386d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockThread::~Thread() { 3878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 390d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void* ThreadEntry(void* arg) { 392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Thread* thread = reinterpret_cast<Thread*>(arg); 393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This is also initialized by the first argument to pthread_create() but we 394d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // don't know which thread will run first (the original thread or the new 395d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // one) so we initialize it here too. 3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread->data()->thread_ = pthread_self(); 3978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 39844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate()); 399d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block thread->Run(); 400d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return NULL; 401d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 402d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 403d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 4049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 4059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block strncpy(name_, name, sizeof(name_)); 4069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 4079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 4089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 4099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 410d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::Start() { 41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t* attr_ptr = NULL; 41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_t attr; 41344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (stack_size_ > 0) { 41444f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_init(&attr); 41544f0eee88ff00398ff7f715fab053374d808c90dSteve Block pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 41644f0eee88ff00398ff7f715fab053374d808c90dSteve Block attr_ptr = &attr; 41744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 4188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 419d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(IsValid()); 420d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 421d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 422d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 423d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::Join() { 4248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_join(data_->thread_, NULL); 425d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 426d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 427d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 428d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 429d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t key; 430d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_key_create(&key, NULL); 431d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(result); 432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return static_cast<LocalStorageKey>(key); 434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 437d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 438d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_key_delete(pthread_key); 440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(result); 441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 442d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 443d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 444d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 445d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 446d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 447d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return pthread_getspecific(pthread_key); 448d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 449d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 450d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 451d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 452d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 453d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_setspecific(pthread_key, value); 454d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 455d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 456d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 457d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Thread::YieldCPU() { 458d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sched_yield(); 459d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 460d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 461d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 462d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass OpenBSDMutex : public Mutex { 463d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 464d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 465d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block OpenBSDMutex() { 466d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_mutexattr_t attrs; 467d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_mutexattr_init(&attrs); 468d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 469d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 470d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 471d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result = pthread_mutex_init(&mutex_, &attrs); 472d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ASSERT(result == 0); 473d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 474d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 475d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~OpenBSDMutex() { pthread_mutex_destroy(&mutex_); } 476d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 477d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual int Lock() { 478d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_mutex_lock(&mutex_); 479d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return result; 480d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 481d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 482d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual int Unlock() { 483d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = pthread_mutex_unlock(&mutex_); 484d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return result; 485d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 486d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 487d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 488d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 489d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 490d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 491d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 492d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockMutex* OS::CreateMutex() { 493d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new OpenBSDMutex(); 494d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 495d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 496d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 497d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass OpenBSDSemaphore : public Semaphore { 498d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 499d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block explicit OpenBSDSemaphore(int count) { sem_init(&sem_, 0, count); } 500d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual ~OpenBSDSemaphore() { sem_destroy(&sem_); } 501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void Wait(); 503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual bool Wait(int timeout); 504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block virtual void Signal() { sem_post(&sem_); } 505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block private: 506d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sem_t sem_; 507d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 508d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 509d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 510d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid OpenBSDSemaphore::Wait() { 511d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block while (true) { 512d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = sem_wait(&sem_); 513d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result == 0) return; // Successfully got semaphore. 514d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 515d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 516d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 517d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 518d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 519d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockbool OpenBSDSemaphore::Wait(int timeout) { 520d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block const long kOneSecondMicros = 1000000; // NOLINT 521d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 522d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Split timeout into second and nanosecond parts. 523d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timeval delta; 524d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delta.tv_usec = timeout % kOneSecondMicros; 525d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delta.tv_sec = timeout / kOneSecondMicros; 526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 527d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timeval current_time; 528d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Get the current time. 529d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (gettimeofday(¤t_time, NULL) == -1) { 530d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return false; 531d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 532d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 533d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Calculate time for end of timeout. 534d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timeval end_time; 535d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block timeradd(¤t_time, &delta, &end_time); 536d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 537d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct timespec ts; 538d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TIMEVAL_TO_TIMESPEC(&end_time, &ts); 539d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block while (true) { 540d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int result = sem_trywait(&sem_); 541d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result == 0) return true; // Successfully got semaphore. 542d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 543d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 544d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 545d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 546d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 547d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 548d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockSemaphore* OS::CreateSemaphore(int count) { 549d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return new OpenBSDSemaphore(count); 550d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 551d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 552d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 553d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#ifdef ENABLE_LOGGING_AND_PROFILING 554d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 555d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic Sampler* active_sampler_ = NULL; 556d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 557d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 558d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block USE(info); 559d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (signal != SIGPROF) return; 560d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (active_sampler_ == NULL) return; 561d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 562d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block TickSample sample; 563d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 564d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // We always sample the VM state. 5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block sample.state = VMState::current_state(); 566d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 567d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block active_sampler_->Tick(&sample); 568d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 569d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 570d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 571d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockclass Sampler::PlatformData : public Malloced { 572d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block public: 573d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block PlatformData() { 574d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block signal_handler_installed_ = false; 575d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 576d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 577d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block bool signal_handler_installed_; 578d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct sigaction old_signal_handler_; 579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct itimerval old_timer_value_; 580d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}; 581d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 582d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 58344f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 58444f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 58544f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 5878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 5888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 589d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block data_ = new PlatformData(); 590d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 591d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 592d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 593d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockSampler::~Sampler() { 594d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block delete data_; 595d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 596d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 597d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 598d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Sampler::Start() { 599d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // There can only be one active sampler at the time on POSIX 600d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // platforms. 601d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (active_sampler_ != NULL) return; 602d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 603d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Request profiling signals. 604d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block struct sigaction sa; 605d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sa.sa_sigaction = ProfilerSignalHandler; 606d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sigemptyset(&sa.sa_mask); 607d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sa.sa_flags = SA_SIGINFO; 608d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; 609d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block data_->signal_handler_installed_ = true; 610d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 611d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set the itimer to generate a tick for each interval. 612d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block itimerval itimer; 613d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block itimer.it_interval.tv_sec = interval_ / 1000; 614d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; 615d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block itimer.it_value.tv_sec = itimer.it_interval.tv_sec; 616d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block itimer.it_value.tv_usec = itimer.it_interval.tv_usec; 617d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); 618d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 619d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Set this sampler as the active sampler. 620d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block active_sampler_ = this; 621d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block active_ = true; 622d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 623d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 624d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 625d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockvoid Sampler::Stop() { 626d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Restore old signal handler 627d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block if (data_->signal_handler_installed_) { 628d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL); 629d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block sigaction(SIGPROF, &data_->old_signal_handler_, 0); 630d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block data_->signal_handler_installed_ = false; 631d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block } 632d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 633d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // This sampler is no longer the active sampler. 634d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block active_sampler_ = NULL; 635d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block active_ = false; 636d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 637d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 638d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block#endif // ENABLE_LOGGING_AND_PROFILING 639d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 640d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} } // namespace v8::internal 641