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