• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LocalTimezone(double time,TimezoneCache * cache)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 
LocalTimeOffset(TimezoneCache * cache)48 double OS::LocalTimeOffset(TimezoneCache* cache) {
49   tzset();
50   return -static_cast<double>(timezone * msPerSecond);
51 }
52 
53 
Allocate(const size_t requested,size_t * allocated,bool is_executable)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 
GetSharedLibraryAddresses()67 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
68   return std::vector<SharedLibraryAddress>();
69 }
70 
71 
SignalCodeMovingGC()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 
VirtualMemory()81 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
82 
83 
VirtualMemory(size_t size)84 VirtualMemory::VirtualMemory(size_t size)
85     : address_(ReserveRegion(size)), size_(size) { }
86 
87 
VirtualMemory(size_t size,size_t alignment)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 
~VirtualMemory()128 VirtualMemory::~VirtualMemory() {
129   if (IsReserved()) {
130     bool result = ReleaseRegion(address(), size());
131     DCHECK(result);
132     USE(result);
133   }
134 }
135 
136 
IsReserved()137 bool VirtualMemory::IsReserved() {
138   return address_ != NULL;
139 }
140 
141 
Reset()142 void VirtualMemory::Reset() {
143   address_ = NULL;
144   size_ = 0;
145 }
146 
147 
Commit(void * address,size_t size,bool is_executable)148 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
149   return CommitRegion(address, size, is_executable);
150 }
151 
152 
Uncommit(void * address,size_t size)153 bool VirtualMemory::Uncommit(void* address, size_t size) {
154   return UncommitRegion(address, size);
155 }
156 
157 
Guard(void * address)158 bool VirtualMemory::Guard(void* address) {
159   OS::Guard(address, OS::CommitPageSize());
160   return true;
161 }
162 
163 
ReserveRegion(size_t size)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 
CommitRegion(void * base,size_t size,bool is_executable)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 
UncommitRegion(void * base,size_t size)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 
ReleasePartialRegion(void * base,size_t size,void * free_start,size_t free_size)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 
ReleaseRegion(void * base,size_t size)206 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
207   return munmap(base, size) == 0;
208 }
209 
210 
HasLazyCommits()211 bool VirtualMemory::HasLazyCommits() {
212   // TODO(alph): implement for the platform.
213   return false;
214 }
215 
216 }  // namespace base
217 }  // namespace v8
218