• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 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 QNX goes here. For the POSIX-compatible
6 // parts the implementation is in platform-posix.cc.
7 
8 #include <backtrace.h>
9 #include <pthread.h>
10 #include <semaphore.h>
11 #include <signal.h>
12 #include <stdlib.h>
13 #include <sys/resource.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <ucontext.h>
17 
18 // QNX requires memory pages to be marked as executable.
19 // Otherwise, the OS raises an exception when executing code in that page.
20 #include <errno.h>
21 #include <fcntl.h>      // open
22 #include <stdarg.h>
23 #include <strings.h>    // index
24 #include <sys/mman.h>   // mmap & munmap
25 #include <sys/procfs.h>
26 #include <sys/stat.h>   // open
27 #include <unistd.h>     // sysconf
28 
29 #include <cmath>
30 
31 #undef MAP_TYPE
32 
33 #include "src/base/macros.h"
34 #include "src/base/platform/platform.h"
35 
36 
37 namespace v8 {
38 namespace base {
39 
40 // 0 is never a valid thread id on Qnx since tids and pids share a
41 // name space and pid 0 is reserved (see man 2 kill).
42 static const pthread_t kNoThread = (pthread_t) 0;
43 
44 
45 #ifdef __arm__
46 
ArmUsingHardFloat()47 bool OS::ArmUsingHardFloat() {
48   // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
49   // the Floating Point ABI used (PCS stands for Procedure Call Standard).
50   // We use these as well as a couple of other defines to statically determine
51   // what FP ABI used.
52   // GCC versions 4.4 and below don't support hard-fp.
53   // GCC versions 4.5 may support hard-fp without defining __ARM_PCS or
54   // __ARM_PCS_VFP.
55 
56 #define GCC_VERSION (__GNUC__ * 10000                                          \
57                      + __GNUC_MINOR__ * 100                                    \
58                      + __GNUC_PATCHLEVEL__)
59 #if GCC_VERSION >= 40600
60 #if defined(__ARM_PCS_VFP)
61   return true;
62 #else
63   return false;
64 #endif
65 
66 #elif GCC_VERSION < 40500
67   return false;
68 
69 #else
70 #if defined(__ARM_PCS_VFP)
71   return true;
72 #elif defined(__ARM_PCS) || defined(__SOFTFP__) || defined(__SOFTFP) || \
73       !defined(__VFP_FP__)
74   return false;
75 #else
76 #error "Your version of GCC does not report the FP ABI compiled for."          \
77        "Please report it on this issue"                                        \
78        "http://code.google.com/p/v8/issues/detail?id=2140"
79 
80 #endif
81 #endif
82 #undef GCC_VERSION
83 }
84 
85 #endif  // __arm__
86 
87 
LocalTimezone(double time,TimezoneCache * cache)88 const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
89   if (std::isnan(time)) return "";
90   time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
91   struct tm tm;
92   struct tm* t = localtime_r(&tv, &tm);
93   if (NULL == t) return "";
94   return t->tm_zone;
95 }
96 
97 
LocalTimeOffset(TimezoneCache * cache)98 double OS::LocalTimeOffset(TimezoneCache* cache) {
99   time_t tv = time(NULL);
100   struct tm tm;
101   struct tm* t = localtime_r(&tv, &tm);
102   // tm_gmtoff includes any daylight savings offset, so subtract it.
103   return static_cast<double>(t->tm_gmtoff * msPerSecond -
104                              (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
105 }
106 
107 
Allocate(const size_t requested,size_t * allocated,bool is_executable)108 void* OS::Allocate(const size_t requested,
109                    size_t* allocated,
110                    bool is_executable) {
111   const size_t msize = RoundUp(requested, AllocateAlignment());
112   int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
113   void* addr = OS::GetRandomMmapAddr();
114   void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
115   if (mbase == MAP_FAILED) return NULL;
116   *allocated = msize;
117   return mbase;
118 }
119 
120 
GetSharedLibraryAddresses()121 std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
122   std::vector<SharedLibraryAddress> result;
123   procfs_mapinfo *mapinfos = NULL, *mapinfo;
124   int proc_fd, num, i;
125 
126   struct {
127     procfs_debuginfo info;
128     char buff[PATH_MAX];
129   } map;
130 
131   char buf[PATH_MAX + 1];
132   snprintf(buf, PATH_MAX + 1, "/proc/%d/as", getpid());
133 
134   if ((proc_fd = open(buf, O_RDONLY)) == -1) {
135     close(proc_fd);
136     return result;
137   }
138 
139   /* Get the number of map entries.  */
140   if (devctl(proc_fd, DCMD_PROC_MAPINFO, NULL, 0, &num) != EOK) {
141     close(proc_fd);
142     return result;
143   }
144 
145   mapinfos = reinterpret_cast<procfs_mapinfo *>(
146       malloc(num * sizeof(procfs_mapinfo)));
147   if (mapinfos == NULL) {
148     close(proc_fd);
149     return result;
150   }
151 
152   /* Fill the map entries.  */
153   if (devctl(proc_fd, DCMD_PROC_PAGEDATA,
154       mapinfos, num * sizeof(procfs_mapinfo), &num) != EOK) {
155     free(mapinfos);
156     close(proc_fd);
157     return result;
158   }
159 
160   for (i = 0; i < num; i++) {
161     mapinfo = mapinfos + i;
162     if (mapinfo->flags & MAP_ELF) {
163       map.info.vaddr = mapinfo->vaddr;
164       if (devctl(proc_fd, DCMD_PROC_MAPDEBUG, &map, sizeof(map), 0) != EOK) {
165         continue;
166       }
167       result.push_back(SharedLibraryAddress(
168           map.info.path, mapinfo->vaddr, mapinfo->vaddr + mapinfo->size));
169     }
170   }
171   free(mapinfos);
172   close(proc_fd);
173   return result;
174 }
175 
176 
SignalCodeMovingGC()177 void OS::SignalCodeMovingGC() {
178 }
179 
180 
181 // Constants used for mmap.
182 static const int kMmapFd = -1;
183 static const int kMmapFdOffset = 0;
184 
185 
VirtualMemory()186 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
187 
188 
VirtualMemory(size_t size)189 VirtualMemory::VirtualMemory(size_t size)
190     : address_(ReserveRegion(size)), size_(size) { }
191 
192 
VirtualMemory(size_t size,size_t alignment)193 VirtualMemory::VirtualMemory(size_t size, size_t alignment)
194     : address_(NULL), size_(0) {
195   DCHECK((alignment % OS::AllocateAlignment()) == 0);
196   size_t request_size = RoundUp(size + alignment,
197                                 static_cast<intptr_t>(OS::AllocateAlignment()));
198   void* reservation = mmap(OS::GetRandomMmapAddr(),
199                            request_size,
200                            PROT_NONE,
201                            MAP_PRIVATE | MAP_ANONYMOUS | MAP_LAZY,
202                            kMmapFd,
203                            kMmapFdOffset);
204   if (reservation == MAP_FAILED) return;
205 
206   uint8_t* base = static_cast<uint8_t*>(reservation);
207   uint8_t* aligned_base = RoundUp(base, alignment);
208   DCHECK_LE(base, aligned_base);
209 
210   // Unmap extra memory reserved before and after the desired block.
211   if (aligned_base != base) {
212     size_t prefix_size = static_cast<size_t>(aligned_base - base);
213     OS::Free(base, prefix_size);
214     request_size -= prefix_size;
215   }
216 
217   size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
218   DCHECK_LE(aligned_size, request_size);
219 
220   if (aligned_size != request_size) {
221     size_t suffix_size = request_size - aligned_size;
222     OS::Free(aligned_base + aligned_size, suffix_size);
223     request_size -= suffix_size;
224   }
225 
226   DCHECK(aligned_size == request_size);
227 
228   address_ = static_cast<void*>(aligned_base);
229   size_ = aligned_size;
230 }
231 
232 
~VirtualMemory()233 VirtualMemory::~VirtualMemory() {
234   if (IsReserved()) {
235     bool result = ReleaseRegion(address(), size());
236     DCHECK(result);
237     USE(result);
238   }
239 }
240 
241 
IsReserved()242 bool VirtualMemory::IsReserved() {
243   return address_ != NULL;
244 }
245 
246 
Reset()247 void VirtualMemory::Reset() {
248   address_ = NULL;
249   size_ = 0;
250 }
251 
252 
Commit(void * address,size_t size,bool is_executable)253 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
254   return CommitRegion(address, size, is_executable);
255 }
256 
257 
Uncommit(void * address,size_t size)258 bool VirtualMemory::Uncommit(void* address, size_t size) {
259   return UncommitRegion(address, size);
260 }
261 
262 
Guard(void * address)263 bool VirtualMemory::Guard(void* address) {
264   OS::Guard(address, OS::CommitPageSize());
265   return true;
266 }
267 
268 
ReserveRegion(size_t size)269 void* VirtualMemory::ReserveRegion(size_t size) {
270   void* result = mmap(OS::GetRandomMmapAddr(),
271                       size,
272                       PROT_NONE,
273                       MAP_PRIVATE | MAP_ANONYMOUS | MAP_LAZY,
274                       kMmapFd,
275                       kMmapFdOffset);
276 
277   if (result == MAP_FAILED) return NULL;
278 
279   return result;
280 }
281 
282 
CommitRegion(void * base,size_t size,bool is_executable)283 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
284   int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
285   if (MAP_FAILED == mmap(base,
286                          size,
287                          prot,
288                          MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
289                          kMmapFd,
290                          kMmapFdOffset)) {
291     return false;
292   }
293 
294   return true;
295 }
296 
297 
UncommitRegion(void * base,size_t size)298 bool VirtualMemory::UncommitRegion(void* base, size_t size) {
299   return mmap(base,
300               size,
301               PROT_NONE,
302               MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_LAZY,
303               kMmapFd,
304               kMmapFdOffset) != MAP_FAILED;
305 }
306 
307 
ReleaseRegion(void * base,size_t size)308 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
309   return munmap(base, size) == 0;
310 }
311 
312 
HasLazyCommits()313 bool VirtualMemory::HasLazyCommits() {
314   return false;
315 }
316 
317 }  // namespace base
318 }  // namespace v8
319