1// Copyright 2012 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Platform-specific code for Solaris 10 goes here. For the POSIX-compatible 6// parts, the implementation is in platform-posix.cc. 7 8#ifdef __sparc 9# error "V8 does not support the SPARC CPU architecture." 10#endif 11 12#include <dlfcn.h> // dladdr 13#include <errno.h> 14#include <ieeefp.h> // finite() 15#include <pthread.h> 16#include <semaphore.h> 17#include <signal.h> // sigemptyset(), etc 18#include <sys/mman.h> // mmap() 19#include <sys/regset.h> 20#include <sys/stack.h> // for stack alignment 21#include <sys/time.h> // gettimeofday(), timeradd() 22#include <time.h> 23#include <ucontext.h> // walkstack(), getcontext() 24#include <unistd.h> // getpagesize(), usleep() 25 26#include <cmath> 27 28#undef MAP_TYPE 29 30#include "src/base/macros.h" 31#include "src/base/platform/platform.h" 32 33 34namespace v8 { 35namespace base { 36 37 38const char* OS::LocalTimezone(double time, TimezoneCache* cache) { 39 if (std::isnan(time)) return ""; 40 time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); 41 struct tm tm; 42 struct tm* t = localtime_r(&tv, &tm); 43 if (NULL == t) return ""; 44 return tzname[0]; // The location of the timezone string on Solaris. 45} 46 47 48double OS::LocalTimeOffset(TimezoneCache* cache) { 49 tzset(); 50 return -static_cast<double>(timezone * msPerSecond); 51} 52 53 54void* OS::Allocate(const size_t requested, 55 size_t* allocated, 56 bool is_executable) { 57 const size_t msize = RoundUp(requested, getpagesize()); 58 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 59 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); 60 61 if (mbase == MAP_FAILED) return NULL; 62 *allocated = msize; 63 return mbase; 64} 65 66 67std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { 68 return std::vector<SharedLibraryAddress>(); 69} 70 71 72void OS::SignalCodeMovingGC() { 73} 74 75 76// Constants used for mmap. 77static const int kMmapFd = -1; 78static const int kMmapFdOffset = 0; 79 80 81VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 82 83 84VirtualMemory::VirtualMemory(size_t size) 85 : address_(ReserveRegion(size)), size_(size) { } 86 87 88VirtualMemory::VirtualMemory(size_t size, size_t alignment) 89 : address_(NULL), size_(0) { 90 DCHECK((alignment % OS::AllocateAlignment()) == 0); 91 size_t request_size = RoundUp(size + alignment, 92 static_cast<intptr_t>(OS::AllocateAlignment())); 93 void* reservation = mmap(OS::GetRandomMmapAddr(), 94 request_size, 95 PROT_NONE, 96 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 97 kMmapFd, 98 kMmapFdOffset); 99 if (reservation == MAP_FAILED) return; 100 101 uint8_t* base = static_cast<uint8_t*>(reservation); 102 uint8_t* aligned_base = RoundUp(base, alignment); 103 DCHECK_LE(base, aligned_base); 104 105 // Unmap extra memory reserved before and after the desired block. 106 if (aligned_base != base) { 107 size_t prefix_size = static_cast<size_t>(aligned_base - base); 108 OS::Free(base, prefix_size); 109 request_size -= prefix_size; 110 } 111 112 size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 113 DCHECK_LE(aligned_size, request_size); 114 115 if (aligned_size != request_size) { 116 size_t suffix_size = request_size - aligned_size; 117 OS::Free(aligned_base + aligned_size, suffix_size); 118 request_size -= suffix_size; 119 } 120 121 DCHECK(aligned_size == request_size); 122 123 address_ = static_cast<void*>(aligned_base); 124 size_ = aligned_size; 125} 126 127 128VirtualMemory::~VirtualMemory() { 129 if (IsReserved()) { 130 bool result = ReleaseRegion(address(), size()); 131 DCHECK(result); 132 USE(result); 133 } 134} 135 136 137bool VirtualMemory::IsReserved() { 138 return address_ != NULL; 139} 140 141 142void VirtualMemory::Reset() { 143 address_ = NULL; 144 size_ = 0; 145} 146 147 148bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 149 return CommitRegion(address, size, is_executable); 150} 151 152 153bool VirtualMemory::Uncommit(void* address, size_t size) { 154 return UncommitRegion(address, size); 155} 156 157 158bool VirtualMemory::Guard(void* address) { 159 OS::Guard(address, OS::CommitPageSize()); 160 return true; 161} 162 163 164void* VirtualMemory::ReserveRegion(size_t size) { 165 void* result = mmap(OS::GetRandomMmapAddr(), 166 size, 167 PROT_NONE, 168 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 169 kMmapFd, 170 kMmapFdOffset); 171 172 if (result == MAP_FAILED) return NULL; 173 174 return result; 175} 176 177 178bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 179 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 180 if (MAP_FAILED == mmap(base, 181 size, 182 prot, 183 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 184 kMmapFd, 185 kMmapFdOffset)) { 186 return false; 187 } 188 return true; 189} 190 191 192bool VirtualMemory::UncommitRegion(void* base, size_t size) { 193 return mmap(base, 194 size, 195 PROT_NONE, 196 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, 197 kMmapFd, 198 kMmapFdOffset) != MAP_FAILED; 199} 200 201bool VirtualMemory::ReleasePartialRegion(void* base, size_t size, 202 void* free_start, size_t free_size) { 203 return munmap(free_start, free_size) == 0; 204} 205 206bool VirtualMemory::ReleaseRegion(void* base, size_t size) { 207 return munmap(base, size) == 0; 208} 209 210 211bool VirtualMemory::HasLazyCommits() { 212 // TODO(alph): implement for the platform. 213 return false; 214} 215 216} // namespace base 217} // namespace v8 218