blob: b9a2ec8e2ebcffc91b916f53c77c1c66d5df165f [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034namespace 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* t = localtime(&tv);
42 if (NULL == t) return "";
43 return tzname[0]; // The location of the timezone string on Solaris.
44}
45
46
47double OS::LocalTimeOffset(TimezoneCache* cache) {
48 tzset();
49 return -static_cast<double>(timezone * msPerSecond);
50}
51
52
53void* OS::Allocate(const size_t requested,
54 size_t* allocated,
55 bool is_executable) {
56 const size_t msize = RoundUp(requested, getpagesize());
57 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
58 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
59
60 if (mbase == MAP_FAILED) return NULL;
61 *allocated = msize;
62 return mbase;
63}
64
65
66class PosixMemoryMappedFile : public OS::MemoryMappedFile {
67 public:
68 PosixMemoryMappedFile(FILE* file, void* memory, int size)
69 : file_(file), memory_(memory), size_(size) { }
70 virtual ~PosixMemoryMappedFile();
71 virtual void* memory() { return memory_; }
72 virtual int size() { return size_; }
73 private:
74 FILE* file_;
75 void* memory_;
76 int size_;
77};
78
79
80OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
81 FILE* file = fopen(name, "r+");
82 if (file == NULL) return NULL;
83
84 fseek(file, 0, SEEK_END);
85 int size = ftell(file);
86
87 void* memory =
88 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
89 return new PosixMemoryMappedFile(file, memory, size);
90}
91
92
93OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
94 void* initial) {
95 FILE* file = fopen(name, "w+");
96 if (file == NULL) return NULL;
97 int result = fwrite(initial, size, 1, file);
98 if (result < 1) {
99 fclose(file);
100 return NULL;
101 }
102 void* memory =
103 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
104 return new PosixMemoryMappedFile(file, memory, size);
105}
106
107
108PosixMemoryMappedFile::~PosixMemoryMappedFile() {
109 if (memory_) munmap(memory_, size_);
110 fclose(file_);
111}
112
113
114std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
115 return std::vector<SharedLibraryAddress>();
116}
117
118
119void OS::SignalCodeMovingGC() {
120}
121
122
123// Constants used for mmap.
124static const int kMmapFd = -1;
125static const int kMmapFdOffset = 0;
126
127
128VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
129
130
131VirtualMemory::VirtualMemory(size_t size)
132 : address_(ReserveRegion(size)), size_(size) { }
133
134
135VirtualMemory::VirtualMemory(size_t size, size_t alignment)
136 : address_(NULL), size_(0) {
137 DCHECK((alignment % OS::AllocateAlignment()) == 0);
138 size_t request_size = RoundUp(size + alignment,
139 static_cast<intptr_t>(OS::AllocateAlignment()));
140 void* reservation = mmap(OS::GetRandomMmapAddr(),
141 request_size,
142 PROT_NONE,
143 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
144 kMmapFd,
145 kMmapFdOffset);
146 if (reservation == MAP_FAILED) return;
147
148 uint8_t* base = static_cast<uint8_t*>(reservation);
149 uint8_t* aligned_base = RoundUp(base, alignment);
150 DCHECK_LE(base, aligned_base);
151
152 // Unmap extra memory reserved before and after the desired block.
153 if (aligned_base != base) {
154 size_t prefix_size = static_cast<size_t>(aligned_base - base);
155 OS::Free(base, prefix_size);
156 request_size -= prefix_size;
157 }
158
159 size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
160 DCHECK_LE(aligned_size, request_size);
161
162 if (aligned_size != request_size) {
163 size_t suffix_size = request_size - aligned_size;
164 OS::Free(aligned_base + aligned_size, suffix_size);
165 request_size -= suffix_size;
166 }
167
168 DCHECK(aligned_size == request_size);
169
170 address_ = static_cast<void*>(aligned_base);
171 size_ = aligned_size;
172}
173
174
175VirtualMemory::~VirtualMemory() {
176 if (IsReserved()) {
177 bool result = ReleaseRegion(address(), size());
178 DCHECK(result);
179 USE(result);
180 }
181}
182
183
184bool VirtualMemory::IsReserved() {
185 return address_ != NULL;
186}
187
188
189void VirtualMemory::Reset() {
190 address_ = NULL;
191 size_ = 0;
192}
193
194
195bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
196 return CommitRegion(address, size, is_executable);
197}
198
199
200bool VirtualMemory::Uncommit(void* address, size_t size) {
201 return UncommitRegion(address, size);
202}
203
204
205bool VirtualMemory::Guard(void* address) {
206 OS::Guard(address, OS::CommitPageSize());
207 return true;
208}
209
210
211void* VirtualMemory::ReserveRegion(size_t size) {
212 void* result = mmap(OS::GetRandomMmapAddr(),
213 size,
214 PROT_NONE,
215 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
216 kMmapFd,
217 kMmapFdOffset);
218
219 if (result == MAP_FAILED) return NULL;
220
221 return result;
222}
223
224
225bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
226 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
227 if (MAP_FAILED == mmap(base,
228 size,
229 prot,
230 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
231 kMmapFd,
232 kMmapFdOffset)) {
233 return false;
234 }
235 return true;
236}
237
238
239bool VirtualMemory::UncommitRegion(void* base, size_t size) {
240 return mmap(base,
241 size,
242 PROT_NONE,
243 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
244 kMmapFd,
245 kMmapFdOffset) != MAP_FAILED;
246}
247
248
249bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
250 return munmap(base, size) == 0;
251}
252
253
254bool VirtualMemory::HasLazyCommits() {
255 // TODO(alph): implement for the platform.
256 return false;
257}
258
259} } // namespace v8::base