13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Redistribution and use in source and binary forms, with or without 3e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// modification, are permitted provided that the following conditions are 4e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// met: 5e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 6e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// * Redistributions of source code must retain the above copyright 7e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// notice, this list of conditions and the following disclaimer. 8e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// * Redistributions in binary form must reproduce the above 9e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// copyright notice, this list of conditions and the following 10e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// disclaimer in the documentation and/or other materials provided 11e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// with the distribution. 12e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// * Neither the name of Google Inc. nor the names of its 13e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// contributors may be used to endorse or promote products derived 14e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// from this software without specific prior written permission. 15e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 16e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 28e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Platform specific code for Cygwin goes here. For the POSIX comaptible parts 29e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// the implementation is in platform-posix.cc. 30e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 31e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <errno.h> 32e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <pthread.h> 33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <semaphore.h> 34e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <stdarg.h> 35e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <strings.h> // index 36e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <sys/time.h> 37e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <sys/mman.h> // mmap & munmap 38e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include <unistd.h> // sysconf 39e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 40e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#undef MAP_TYPE 41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 42e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "v8.h" 43e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "platform-posix.h" 45e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "platform.h" 46e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "v8threads.h" 47e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "vm-state-inl.h" 48e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#include "win32-headers.h" 49e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 50e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace v8 { 51e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochnamespace internal { 52e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 53e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 0 is never a valid thread id 54e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic const pthread_t kNoThread = (pthread_t) 0; 55e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 56e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 57e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdouble ceiling(double x) { 58e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return ceil(x); 59e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 60e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 61e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Mutex* limit_mutex = NULL; 638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() { 66e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Seed the random number generator. 67e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Convert the current time to a 64-bit integer first, before converting it 68e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // to an unsigned. Going directly can cause an overflow and the seed to be 69e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // set to all ones. The seed will be identical for different instances that 70e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // call this setup code within the same millisecond. 71e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 72e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch srandom(static_cast<unsigned int>(seed)); 738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch limit_mutex = CreateMutex(); 74e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 75e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 76e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() { 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math functions depend on CPU features therefore they are initialized after 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CPU. 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathSetup(); 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 83e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochuint64_t OS::CpuFeaturesImpliedByPlatform() { 84e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return 0; // Nothing special about Cygwin. 85e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 86e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 87e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 88e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint OS::ActivationFrameAlignment() { 89e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // With gcc 4.4 the tree vectorization optimizer can generate code 90e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // that requires 16 byte alignment such as movdqa on x86. 91e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return 16; 92e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 93e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 94e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 95e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 96e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __asm__ __volatile__("" : : : "memory"); 97e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // An x86 store acts as a release barrier. 98e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *ptr = value; 99e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochconst char* OS::LocalTimezone(double time) { 102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (isnan(time)) return ""; 103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch struct tm* t = localtime(&tv); 105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (NULL == t) return ""; 106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return tzname[0]; // The location of the timezone string on Cygwin. 107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 109e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 110e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochdouble OS::LocalTimeOffset() { 111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // On Cygwin, struct tm does not contain a tm_gmtoff field. 112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch time_t utc = time(NULL); 113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(utc != -1); 114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch struct tm* loc = localtime(&utc); 115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(loc != NULL); 116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // time - localtime includes any daylight savings offset, so subtract it. 117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return static_cast<double>((mktime(loc) - utc) * msPerSecond - 118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// We keep the lowest and highest addresses mapped as a quick way of 123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// determining that pointers are outside the heap (used mostly in assertions 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification). The estimate is conservative, i.e., not all addresses in 125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 'allocated' space are actually allocated to our heap. The range is 126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// [lowest, highest), inclusive on the low and and exclusive on the high end. 127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 1328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(limit_mutex != NULL); 1338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ScopedLock lock(limit_mutex); 1348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch lowest_ever_allocated = Min(lowest_ever_allocated, address); 136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch highest_ever_allocated = 137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Max(highest_ever_allocated, 138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool OS::IsOutsideAllocatedSpace(void* address) { 143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return address < lowest_ever_allocated || address >= highest_ever_allocated; 144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochsize_t OS::AllocateAlignment() { 148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return sysconf(_SC_PAGESIZE); 149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid* OS::Allocate(const size_t requested, 153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch size_t* allocated, 154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool is_executable) { 155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE)); 156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (mbase == MAP_FAILED) { 15944f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return NULL; 161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *allocated = msize; 163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UpdateAllocatedSpaceLimits(mbase, msize); 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return mbase; 165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::Free(void* address, const size_t size) { 169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(1240712): munmap has a return value which is ignored here. 170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = munmap(address, size); 171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(result); 172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); 173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 17669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid OS::ProtectCode(void* address, const size_t size) { 17769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DWORD old_protect; 17869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect); 17969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 18069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 18169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 18269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid OS::Guard(void* address, const size_t size) { 18369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch DWORD oldprotect; 18469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect); 18569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 18669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 18769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::Sleep(int milliseconds) { 189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned int ms = static_cast<unsigned int>(milliseconds); 190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch usleep(1000 * ms); 191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::Abort() { 195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Redirect to std abort to signal abnormal program termination. 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch abort(); 197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::DebugBreak() { 201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch asm("int $3"); 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass PosixMemoryMappedFile : public OS::MemoryMappedFile { 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PosixMemoryMappedFile(FILE* file, void* memory, int size) 208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : file_(file), memory_(memory), size_(size) { } 209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual ~PosixMemoryMappedFile(); 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void* memory() { return memory_; } 211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual int size() { return size_; } 212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file_; 214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void* memory_; 215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int size_; 216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "r+"); 221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (file == NULL) return NULL; 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch fseek(file, 0, SEEK_END); 224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int size = ftell(file); 225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void* memory = 227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return new PosixMemoryMappedFile(file, memory, size); 229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void* initial) { 234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* file = fopen(name, "w+"); 235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (file == NULL) return NULL; 236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = fwrite(initial, size, 1, file); 237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (result < 1) { 238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch fclose(file); 239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return NULL; 240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch void* memory = 242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); 243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return new PosixMemoryMappedFile(file, memory, size); 244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochPosixMemoryMappedFile::~PosixMemoryMappedFile() { 248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (memory_) munmap(memory_, size_); 249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch fclose(file_); 250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::LogSharedLibraryAddresses() { 254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This function assumes that the layout of the file is as follows: 255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If we encounter an unexpected situation we abort scanning further entries. 257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FILE* fp = fopen("/proc/self/maps", "r"); 258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (fp == NULL) return; 259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Allocate enough room to be able to store a full file name. 261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const int kLibNameLen = FILENAME_MAX + 1; 262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch i::Isolate* isolate = ISOLATE; 265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This loop will terminate once the scanning hits an EOF. 266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (true) { 267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uintptr_t start, end; 268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch char attr_r, attr_w, attr_x, attr_p; 269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Parse the addresses and permission bits at the beginning of the line. 270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int c; 274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Found a read-only executable entry. Skip characters until we reach 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the beginning of the filename or the end of the line. 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch do { 278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch c = getc(fp); 279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } while ((c != EOF) && (c != '\n') && (c != '/')); 280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (c == EOF) break; // EOF: Was unexpected, just exit. 281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Process the filename if found. 283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (c == '/') { 284e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ungetc(c, fp); // Push the '/' back into the stream to be read below. 285e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Read to the end of the line. Exit if the read fails. 287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (fgets(lib_name, kLibNameLen, fp) == NULL) break; 288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Drop the newline character read by fgets. We do not need to check 290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // for a zero-length string because we know that we at least read the 291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // '/' character. 292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch lib_name[strlen(lib_name) - 1] = '\0'; 293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // No library name found, just record the raw address range. 295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch snprintf(lib_name, kLibNameLen, 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LOG(isolate, SharedLibraryEvent(lib_name, start, end)); 299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Entry not describing executable data. Skip to end of line to set up 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // reading the next entry. 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch do { 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch c = getc(fp); 304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } while ((c != EOF) && (c != '\n')); 305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (c == EOF) break; 306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch free(lib_name); 309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch fclose(fp); 310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid OS::SignalCodeMovingGC() { 314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Nothing to do on Cygwin. 315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochint OS::StackWalk(Vector<OS::StackFrame> frames) { 319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Not supported on Cygwin. 320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return 0; 321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// The VirtualMemory implementation is taken from platform-win32.cc. 3258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// The mmap-based virtual memory implementation as it is used on most posix 3268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// platforms does not work well because Cygwin does not support MAP_FIXED. 3278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// This causes VirtualMemory::Commit to not always commit the memory region 3288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// specified. 3298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochbool VirtualMemory::IsReserved() { 3318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return address_ != NULL; 3328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochVirtualMemory::VirtualMemory(size_t size) { 3368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch address_ = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); 337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch size_ = size; 338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 339e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 340e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochVirtualMemory::~VirtualMemory() { 342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (IsReserved()) { 3438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (0 == VirtualFree(address(), 0, MEM_RELEASE)) address_ = NULL; 344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 3498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 3508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (NULL == VirtualAlloc(address, size, MEM_COMMIT, prot)) { 351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 352e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch UpdateAllocatedSpaceLimits(address, static_cast<int>(size)); 355e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return true; 356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 3608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(IsReserved()); 3618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return VirtualFree(address, size, MEM_DECOMMIT) != false; 362e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) { 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (NULL == VirtualAlloc(address, 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::CommitPageSize(), 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MEM_COMMIT, 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PAGE_READONLY | PAGE_GUARD)) { 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced { 377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 3788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PlatformData() : thread_(kNoThread) {} 379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_t thread_; // Thread handle for pthread. 380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3853fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochThread::Thread(const Options& options) 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : data_(new PlatformData()), 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stack_size_(options.stack_size()) { 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_name(options.name()); 389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 390e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 391e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 392e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochThread::~Thread() { 3938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete data_; 394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 397e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic void* ThreadEntry(void* arg) { 398e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Thread* thread = reinterpret_cast<Thread*>(arg); 399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // This is also initialized by the first argument to pthread_create() but we 400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // don't know which thread will run first (the original thread or the new 401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // one) so we initialize it here too. 4028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch thread->data()->thread_ = pthread_self(); 4038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(thread->data()->thread_ != kNoThread); 404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch thread->Run(); 405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return NULL; 406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Thread::set_name(const char* name) { 410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch strncpy(name_, name, sizeof(name_)); 411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch name_[sizeof(name_) - 1] = '\0'; 412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Thread::Start() { 4168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_attr_t* attr_ptr = NULL; 4178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_attr_t attr; 4188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (stack_size_ > 0) { 4198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_attr_init(&attr); 4208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 4218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch attr_ptr = &attr; 4228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 4248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(data_->thread_ != kNoThread); 425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Thread::Join() { 4298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch pthread_join(data_->thread_, NULL); 430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic inline Thread::LocalStorageKey PthreadKeyToLocalKey( 434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_key_t pthread_key) { 435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps 436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // because pthread_key_t is a pointer type on Cygwin. This will probably not 437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway. 438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); 439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key); 440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return static_cast<Thread::LocalStorageKey>(ptr_key); 441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic inline pthread_key_t LocalKeyToPthreadKey( 445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Thread::LocalStorageKey local_key) { 446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t)); 447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch intptr_t ptr_key = static_cast<intptr_t>(local_key); 448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return reinterpret_cast<pthread_key_t>(ptr_key); 449e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochThread::LocalStorageKey Thread::CreateThreadLocalKey() { 453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_key_t key; 454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = pthread_key_create(&key, NULL); 455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(result); 456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); 457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return PthreadKeyToLocalKey(key); 458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 461e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 462e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_key_t pthread_key = LocalKeyToPthreadKey(key); 463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = pthread_key_delete(pthread_key); 464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(result); 465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); 466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid* Thread::GetThreadLocal(LocalStorageKey key) { 470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_key_t pthread_key = LocalKeyToPthreadKey(key); 471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return pthread_getspecific(pthread_key); 472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_key_t pthread_key = LocalKeyToPthreadKey(key); 477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_setspecific(pthread_key, value); 478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 481e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Thread::YieldCPU() { 482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch sched_yield(); 483e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 486e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass CygwinMutex : public Mutex { 487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 488e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CygwinMutex() { 489e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_mutexattr_t attrs; 490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch memset(&attrs, 0, sizeof(attrs)); 491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 492e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = pthread_mutexattr_init(&attrs); 493e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); 494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); 496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch result = pthread_mutex_init(&mutex_, &attrs); 497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); 498e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual ~CygwinMutex() { pthread_mutex_destroy(&mutex_); } 501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual int Lock() { 503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = pthread_mutex_lock(&mutex_); 504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return result; 505e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual int Unlock() { 508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = pthread_mutex_unlock(&mutex_); 509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return result; 510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual bool TryLock() { 513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = pthread_mutex_trylock(&mutex_); 514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return false if the lock is busy and locking failed. 515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (result == EBUSY) { 516e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 517e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(result == 0); // Verify no other errors. 519e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return true; 520e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochMutex* OS::CreateMutex() { 528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return new CygwinMutex(); 529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass CygwinSemaphore : public Semaphore { 533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch explicit CygwinSemaphore(int count) { sem_init(&sem_, 0, count); } 535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual ~CygwinSemaphore() { sem_destroy(&sem_); } 536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Wait(); 538e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual bool Wait(int timeout); 539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch virtual void Signal() { sem_post(&sem_); } 540e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch private: 541e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch sem_t sem_; 542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 545e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid CygwinSemaphore::Wait() { 546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (true) { 547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = sem_wait(&sem_); 548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (result == 0) return; // Successfully got semaphore. 549e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 551e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 552e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 553e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#ifndef TIMEVAL_TO_TIMESPEC 555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ 556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (ts)->tv_sec = (tv)->tv_sec; \ 557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (ts)->tv_nsec = (tv)->tv_usec * 1000; \ 558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} while (false) 559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif 560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool CygwinSemaphore::Wait(int timeout) { 563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const long kOneSecondMicros = 1000000; // NOLINT 564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Split timeout into second and nanosecond parts. 566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch struct timeval delta; 567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch delta.tv_usec = timeout % kOneSecondMicros; 568e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch delta.tv_sec = timeout / kOneSecondMicros; 569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch struct timeval current_time; 571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Get the current time. 572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (gettimeofday(¤t_time, NULL) == -1) { 573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 575e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 576e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Calculate time for end of timeout. 577e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch struct timeval end_time; 578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch timeradd(¤t_time, &delta, &end_time); 579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 580e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch struct timespec ts; 581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TIMEVAL_TO_TIMESPEC(&end_time, &ts); 582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Wait for semaphore signalled or timeout. 583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (true) { 584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int result = sem_timedwait(&sem_, &ts); 585e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (result == 0) return true; // Successfully got semaphore. 586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 588e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 589e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 590e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochSemaphore* OS::CreateSemaphore(int count) { 593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return new CygwinSemaphore(count); 594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 597e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// ---------------------------------------------------------------------------- 598e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Cygwin profiler support. 599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// 600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// On Cygwin we use the same sampler implementation as on win32. 601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochclass Sampler::PlatformData : public Malloced { 603e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch public: 6048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Get a handle to the calling thread. This is the thread that we are 6058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // going to profile. We need to make a copy of the handle because we are 6068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // going to use it in the sampler thread. Using GetThreadHandle() will 6078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // not work in this case. We're using OpenThread because DuplicateHandle 6088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // for some reason doesn't work in Chrome's sandbox. 6098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | 6108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch THREAD_SUSPEND_RESUME | 6118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch THREAD_QUERY_INFORMATION, 6128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch false, 6138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GetCurrentThreadId())) {} 6148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ~PlatformData() { 6168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (profiled_thread_ != NULL) { 6178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CloseHandle(profiled_thread_); 6188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch profiled_thread_ = NULL; 6198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HANDLE profiled_thread() { return profiled_thread_; } 6238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch private: 625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HANDLE profiled_thread_; 6268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}; 6278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass SamplerThread : public Thread { 6308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch public: 6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSamplerThreadStackSize = 64 * KB; 6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch explicit SamplerThread(int interval) 6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), 6358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch interval_(interval) {} 6368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static void AddActiveSampler(Sampler* sampler) { 6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 6398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerRegistry::AddActiveSampler(sampler); 6408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (instance_ == NULL) { 6418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instance_ = new SamplerThread(sampler->interval()); 6428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instance_->Start(); 6438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 6448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(instance_->interval_ == sampler->interval()); 6458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static void RemoveActiveSampler(Sampler* sampler) { 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 6508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerRegistry::RemoveActiveSampler(sampler); 6518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 6523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 6538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch delete instance_; 6548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instance_ = NULL; 655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 657e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Implement Thread::Run(). 6598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch virtual void Run() { 6608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerRegistry::State state; 6618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch while ((state = SamplerRegistry::GetState()) != 6628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerRegistry::HAS_NO_SAMPLERS) { 6638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool cpu_profiling_enabled = 6648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 6658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 6668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // When CPU profiling is enabled both JavaScript and C++ code is 6678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // profiled. We must not suspend. 6688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!cpu_profiling_enabled) { 6698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (rate_limiter_.SuspendIfNecessary()) continue; 6708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (cpu_profiling_enabled) { 6728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 6738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 6748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (runtime_profiler_enabled) { 6778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 6788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 6798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch OS::Sleep(interval_); 6828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) { 6868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!sampler->isolate()->IsInitialized()) return; 6878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!sampler->IsProfiling()) return; 6888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerThread* sampler_thread = 6898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reinterpret_cast<SamplerThread*>(raw_sampler_thread); 6908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sampler_thread->SampleContext(sampler); 6918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 6948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!sampler->isolate()->IsInitialized()) return; 6958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sampler->isolate()->runtime_profiler()->NotifyTick(); 6968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 6978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 6988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch void SampleContext(Sampler* sampler) { 6998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); 7008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (profiled_thread == NULL) return; 7018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 7028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Context used for sampling the register state of the profiled thread. 7038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CONTEXT context; 7048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch memset(&context, 0, sizeof(context)); 705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 7068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TickSample sample_obj; 7078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate()); 7088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (sample == NULL) sample = &sample_obj; 709e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 7108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const DWORD kSuspendFailed = static_cast<DWORD>(-1); 7118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (SuspendThread(profiled_thread) == kSuspendFailed) return; 7128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->state = sampler->isolate()->current_vm_state(); 713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 7148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context.ContextFlags = CONTEXT_FULL; 7158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (GetThreadContext(profiled_thread, &context) != 0) { 716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#if V8_HOST_ARCH_X64 7178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->pc = reinterpret_cast<Address>(context.Rip); 7188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->sp = reinterpret_cast<Address>(context.Rsp); 7198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->fp = reinterpret_cast<Address>(context.Rbp); 720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#else 7218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->pc = reinterpret_cast<Address>(context.Eip); 7228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->sp = reinterpret_cast<Address>(context.Esp); 7238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sample->fp = reinterpret_cast<Address>(context.Ebp); 724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch#endif 7258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sampler->SampleStack(sample); 7268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch sampler->Tick(sample); 727e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 7288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ResumeThread(profiled_thread); 729e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 7308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 7318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch const int interval_; 7328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RuntimeProfilerRateLimiter rate_limiter_; 7338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 7348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Protects the process wide state below. 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static LazyMutex mutex_; 7368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static SamplerThread* instance_; 7378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 7398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DISALLOW_COPY_AND_ASSIGN(SamplerThread); 740e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}; 741e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SamplerThread::mutex_ = LAZY_MUTEX_INITIALIZER; 7448b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochSamplerThread* SamplerThread::instance_ = NULL; 745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 7478b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochSampler::Sampler(Isolate* isolate, int interval) 7488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : isolate_(isolate), 7498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch interval_(interval), 750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch profiling_(false), 751e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch active_(false), 752e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch samples_taken_(0) { 7538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch data_ = new PlatformData; 754e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 755e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 756e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochSampler::~Sampler() { 7588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!IsActive()); 759e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch delete data_; 760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Sampler::Start() { 764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!IsActive()); 765e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SetActive(true); 7668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerThread::AddActiveSampler(this); 767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid Sampler::Stop() { 7718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(IsActive()); 7728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SamplerThread::RemoveActiveSampler(this); 773e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SetActive(false); 774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} } // namespace v8::internal 778