OLD | NEW |
| (Empty) |
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/platform.h" | |
31 #include "src/utils.h" | |
32 | |
33 | |
34 // It seems there is a bug in some Solaris distributions (experienced in | |
35 // SunOS 5.10 Generic_141445-09) which make it difficult or impossible to | |
36 // access signbit() despite the availability of other C99 math functions. | |
37 #ifndef signbit | |
38 namespace std { | |
39 // Test sign - usually defined in math.h | |
40 int signbit(double x) { | |
41 // We need to take care of the special case of both positive and negative | |
42 // versions of zero. | |
43 if (x == 0) { | |
44 return fpclass(x) & FP_NZERO; | |
45 } else { | |
46 // This won't detect negative NaN but that should be okay since we don't | |
47 // assume that behavior. | |
48 return x < 0; | |
49 } | |
50 } | |
51 } // namespace std | |
52 #endif // signbit | |
53 | |
54 namespace v8 { | |
55 namespace internal { | |
56 | |
57 | |
58 const char* OS::LocalTimezone(double time, TimezoneCache* cache) { | |
59 if (std::isnan(time)) return ""; | |
60 time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); | |
61 struct tm* t = localtime(&tv); | |
62 if (NULL == t) return ""; | |
63 return tzname[0]; // The location of the timezone string on Solaris. | |
64 } | |
65 | |
66 | |
67 double OS::LocalTimeOffset(TimezoneCache* cache) { | |
68 tzset(); | |
69 return -static_cast<double>(timezone * msPerSecond); | |
70 } | |
71 | |
72 | |
73 void* OS::Allocate(const size_t requested, | |
74 size_t* allocated, | |
75 bool is_executable) { | |
76 const size_t msize = RoundUp(requested, getpagesize()); | |
77 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); | |
78 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0); | |
79 | |
80 if (mbase == MAP_FAILED) return NULL; | |
81 *allocated = msize; | |
82 return mbase; | |
83 } | |
84 | |
85 | |
86 class PosixMemoryMappedFile : public OS::MemoryMappedFile { | |
87 public: | |
88 PosixMemoryMappedFile(FILE* file, void* memory, int size) | |
89 : file_(file), memory_(memory), size_(size) { } | |
90 virtual ~PosixMemoryMappedFile(); | |
91 virtual void* memory() { return memory_; } | |
92 virtual int size() { return size_; } | |
93 private: | |
94 FILE* file_; | |
95 void* memory_; | |
96 int size_; | |
97 }; | |
98 | |
99 | |
100 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { | |
101 FILE* file = fopen(name, "r+"); | |
102 if (file == NULL) return NULL; | |
103 | |
104 fseek(file, 0, SEEK_END); | |
105 int size = ftell(file); | |
106 | |
107 void* memory = | |
108 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); | |
109 return new PosixMemoryMappedFile(file, memory, size); | |
110 } | |
111 | |
112 | |
113 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, | |
114 void* initial) { | |
115 FILE* file = fopen(name, "w+"); | |
116 if (file == NULL) return NULL; | |
117 int result = fwrite(initial, size, 1, file); | |
118 if (result < 1) { | |
119 fclose(file); | |
120 return NULL; | |
121 } | |
122 void* memory = | |
123 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); | |
124 return new PosixMemoryMappedFile(file, memory, size); | |
125 } | |
126 | |
127 | |
128 PosixMemoryMappedFile::~PosixMemoryMappedFile() { | |
129 if (memory_) munmap(memory_, size_); | |
130 fclose(file_); | |
131 } | |
132 | |
133 | |
134 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { | |
135 return std::vector<SharedLibraryAddress>(); | |
136 } | |
137 | |
138 | |
139 void OS::SignalCodeMovingGC() { | |
140 } | |
141 | |
142 | |
143 // Constants used for mmap. | |
144 static const int kMmapFd = -1; | |
145 static const int kMmapFdOffset = 0; | |
146 | |
147 | |
148 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } | |
149 | |
150 | |
151 VirtualMemory::VirtualMemory(size_t size) | |
152 : address_(ReserveRegion(size)), size_(size) { } | |
153 | |
154 | |
155 VirtualMemory::VirtualMemory(size_t size, size_t alignment) | |
156 : address_(NULL), size_(0) { | |
157 ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); | |
158 size_t request_size = RoundUp(size + alignment, | |
159 static_cast<intptr_t>(OS::AllocateAlignment())); | |
160 void* reservation = mmap(OS::GetRandomMmapAddr(), | |
161 request_size, | |
162 PROT_NONE, | |
163 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, | |
164 kMmapFd, | |
165 kMmapFdOffset); | |
166 if (reservation == MAP_FAILED) return; | |
167 | |
168 uint8_t* base = static_cast<uint8_t*>(reservation); | |
169 uint8_t* aligned_base = RoundUp(base, alignment); | |
170 ASSERT_LE(base, aligned_base); | |
171 | |
172 // Unmap extra memory reserved before and after the desired block. | |
173 if (aligned_base != base) { | |
174 size_t prefix_size = static_cast<size_t>(aligned_base - base); | |
175 OS::Free(base, prefix_size); | |
176 request_size -= prefix_size; | |
177 } | |
178 | |
179 size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); | |
180 ASSERT_LE(aligned_size, request_size); | |
181 | |
182 if (aligned_size != request_size) { | |
183 size_t suffix_size = request_size - aligned_size; | |
184 OS::Free(aligned_base + aligned_size, suffix_size); | |
185 request_size -= suffix_size; | |
186 } | |
187 | |
188 ASSERT(aligned_size == request_size); | |
189 | |
190 address_ = static_cast<void*>(aligned_base); | |
191 size_ = aligned_size; | |
192 } | |
193 | |
194 | |
195 VirtualMemory::~VirtualMemory() { | |
196 if (IsReserved()) { | |
197 bool result = ReleaseRegion(address(), size()); | |
198 ASSERT(result); | |
199 USE(result); | |
200 } | |
201 } | |
202 | |
203 | |
204 bool VirtualMemory::IsReserved() { | |
205 return address_ != NULL; | |
206 } | |
207 | |
208 | |
209 void VirtualMemory::Reset() { | |
210 address_ = NULL; | |
211 size_ = 0; | |
212 } | |
213 | |
214 | |
215 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { | |
216 return CommitRegion(address, size, is_executable); | |
217 } | |
218 | |
219 | |
220 bool VirtualMemory::Uncommit(void* address, size_t size) { | |
221 return UncommitRegion(address, size); | |
222 } | |
223 | |
224 | |
225 bool VirtualMemory::Guard(void* address) { | |
226 OS::Guard(address, OS::CommitPageSize()); | |
227 return true; | |
228 } | |
229 | |
230 | |
231 void* VirtualMemory::ReserveRegion(size_t size) { | |
232 void* result = mmap(OS::GetRandomMmapAddr(), | |
233 size, | |
234 PROT_NONE, | |
235 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, | |
236 kMmapFd, | |
237 kMmapFdOffset); | |
238 | |
239 if (result == MAP_FAILED) return NULL; | |
240 | |
241 return result; | |
242 } | |
243 | |
244 | |
245 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { | |
246 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); | |
247 if (MAP_FAILED == mmap(base, | |
248 size, | |
249 prot, | |
250 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, | |
251 kMmapFd, | |
252 kMmapFdOffset)) { | |
253 return false; | |
254 } | |
255 return true; | |
256 } | |
257 | |
258 | |
259 bool VirtualMemory::UncommitRegion(void* base, size_t size) { | |
260 return mmap(base, | |
261 size, | |
262 PROT_NONE, | |
263 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, | |
264 kMmapFd, | |
265 kMmapFdOffset) != MAP_FAILED; | |
266 } | |
267 | |
268 | |
269 bool VirtualMemory::ReleaseRegion(void* base, size_t size) { | |
270 return munmap(base, size) == 0; | |
271 } | |
272 | |
273 | |
274 bool VirtualMemory::HasLazyCommits() { | |
275 // TODO(alph): implement for the platform. | |
276 return false; | |
277 } | |
278 | |
279 } } // namespace v8::internal | |
OLD | NEW |