Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / v8 / src / base / platform / platform-solaris.cc
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 // 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 base {
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   DCHECK(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   DCHECK_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   DCHECK_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   DCHECK(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     DCHECK(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::base