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 34 namespace v8 { 35 namespace base { 36 37 38 const 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 48 double OS::LocalTimeOffset(TimezoneCache* cache) { 49 tzset(); 50 return -static_cast<double>(timezone * msPerSecond); 51 } 52 53 54 void* 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 67 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { 68 return std::vector<SharedLibraryAddress>(); 69 } 70 71 72 void OS::SignalCodeMovingGC() { 73 } 74 75 76 // Constants used for mmap. 77 static const int kMmapFd = -1; 78 static const int kMmapFdOffset = 0; 79 80 81 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 82 83 84 VirtualMemory::VirtualMemory(size_t size) 85 : address_(ReserveRegion(size)), size_(size) { } 86 87 88 VirtualMemory::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 128 VirtualMemory::~VirtualMemory() { 129 if (IsReserved()) { 130 bool result = ReleaseRegion(address(), size()); 131 DCHECK(result); 132 USE(result); 133 } 134 } 135 136 137 bool VirtualMemory::IsReserved() { 138 return address_ != NULL; 139 } 140 141 142 void VirtualMemory::Reset() { 143 address_ = NULL; 144 size_ = 0; 145 } 146 147 148 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 149 return CommitRegion(address, size, is_executable); 150 } 151 152 153 bool VirtualMemory::Uncommit(void* address, size_t size) { 154 return UncommitRegion(address, size); 155 } 156 157 158 bool VirtualMemory::Guard(void* address) { 159 OS::Guard(address, OS::CommitPageSize()); 160 return true; 161 } 162 163 164 void* 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 178 bool 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 192 bool 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 201 bool 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 206 bool VirtualMemory::ReleaseRegion(void* base, size_t size) { 207 return munmap(base, size) == 0; 208 } 209 210 211 bool VirtualMemory::HasLazyCommits() { 212 // TODO(alph): implement for the platform. 213 return false; 214 } 215 216 } // namespace base 217 } // namespace v8 218