19ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// Copyright 2013 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
49ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
59ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// Platform-specific code for QNX goes here. For the POSIX-compatible
69ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// parts the implementation is in platform-posix.cc.
79ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
89ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <pthread.h>
99ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <semaphore.h>
109ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <signal.h>
119ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/time.h>
129ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/resource.h>
139ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/types.h>
149ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <stdlib.h>
159ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <ucontext.h>
169ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <backtrace.h>
179ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
189ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// QNX requires memory pages to be marked as executable.
199ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// Otherwise, the OS raises an exception when executing code in that page.
209ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/types.h>  // mmap & munmap
219ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/mman.h>   // mmap & munmap
229ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/stat.h>   // open
239ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <fcntl.h>      // open
249ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <unistd.h>     // sysconf
259ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <strings.h>    // index
269ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <errno.h>
279ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <stdarg.h>
289ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#include <sys/procfs.h>
299ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
309ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#undef MAP_TYPE
319ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
32196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
339ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
34196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/platform.h"
359ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
369ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
379ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgnamespace v8 {
389ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgnamespace internal {
399ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
409ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// 0 is never a valid thread id on Qnx since tids and pids share a
419ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// name space and pid 0 is reserved (see man 2 kill).
429ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgstatic const pthread_t kNoThread = (pthread_t) 0;
439ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
449ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
459ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#ifdef __arm__
469ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
479ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool OS::ArmUsingHardFloat() {
489ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
499ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // the Floating Point ABI used (PCS stands for Procedure Call Standard).
509ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // We use these as well as a couple of other defines to statically determine
519ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // what FP ABI used.
529ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // GCC versions 4.4 and below don't support hard-fp.
539ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // GCC versions 4.5 may support hard-fp without defining __ARM_PCS or
549ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // __ARM_PCS_VFP.
559ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
569ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#define GCC_VERSION (__GNUC__ * 10000                                          \
579ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                     + __GNUC_MINOR__ * 100                                    \
589ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                     + __GNUC_PATCHLEVEL__)
599ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#if GCC_VERSION >= 40600
609ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#if defined(__ARM_PCS_VFP)
619ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return true;
629ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#else
639ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return false;
649ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#endif
659ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
669ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#elif GCC_VERSION < 40500
679ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return false;
689ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
699ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#else
709ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#if defined(__ARM_PCS_VFP)
719ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return true;
729ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#elif defined(__ARM_PCS) || defined(__SOFTFP__) || defined(__SOFTFP) || \
739ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      !defined(__VFP_FP__)
749ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return false;
759ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#else
769ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#error "Your version of GCC does not report the FP ABI compiled for."          \
779ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org       "Please report it on this issue"                                        \
789ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org       "http://code.google.com/p/v8/issues/detail?id=2140"
799ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
809ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#endif
819ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#endif
829ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#undef GCC_VERSION
839ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
849ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
859ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#endif  // __arm__
869ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
879ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
886b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgconst char* OS::LocalTimezone(double time, TimezoneCache* cache) {
899ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (std::isnan(time)) return "";
909ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
919ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  struct tm* t = localtime(&tv);
929ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (NULL == t) return "";
939ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return t->tm_zone;
949ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
959ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
969ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
976b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgdouble OS::LocalTimeOffset(TimezoneCache* cache) {
989ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  time_t tv = time(NULL);
999ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  struct tm* t = localtime(&tv);
1009ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // tm_gmtoff includes any daylight savings offset, so subtract it.
1019ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return static_cast<double>(t->tm_gmtoff * msPerSecond -
1029ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                             (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
1039ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
1049ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1059ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1069ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgvoid* OS::Allocate(const size_t requested,
1079ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                   size_t* allocated,
1089ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                   bool is_executable) {
1099ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  const size_t msize = RoundUp(requested, AllocateAlignment());
1109ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
1119ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* addr = OS::GetRandomMmapAddr();
1129ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  if (mbase == MAP_FAILED) return NULL;
1149ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  *allocated = msize;
1159ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return mbase;
1169ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
1179ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1189ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1199ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgclass PosixMemoryMappedFile : public OS::MemoryMappedFile {
1209ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org public:
1219ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  PosixMemoryMappedFile(FILE* file, void* memory, int size)
1229ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    : file_(file), memory_(memory), size_(size) { }
1239ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  virtual ~PosixMemoryMappedFile();
1249ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  virtual void* memory() { return memory_; }
1259ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  virtual int size() { return size_; }
1269ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org private:
1279ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  FILE* file_;
1289ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* memory_;
1299ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  int size_;
1309ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org};
1319ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1329ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1339ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
1349ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  FILE* file = fopen(name, "r+");
1359ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (file == NULL) return NULL;
1369ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1379ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  fseek(file, 0, SEEK_END);
1389ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  int size = ftell(file);
1399ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1409ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* memory =
1419ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      mmap(OS::GetRandomMmapAddr(),
1429ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           size,
1439ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           PROT_READ | PROT_WRITE,
1449ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           MAP_SHARED,
1459ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           fileno(file),
1469ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           0);
1479ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
1489ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
1499ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1509ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1519ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
1529ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    void* initial) {
1539ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  FILE* file = fopen(name, "w+");
1549ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (file == NULL) return NULL;
1559ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  int result = fwrite(initial, size, 1, file);
1569ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (result < 1) {
1579ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    fclose(file);
1589ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    return NULL;
1599ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
1609ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* memory =
1619ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      mmap(OS::GetRandomMmapAddr(),
1629ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           size,
1639ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           PROT_READ | PROT_WRITE,
1649ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           MAP_SHARED,
1659ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           fileno(file),
1669ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org           0);
1679ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return new PosixMemoryMappedFile(file, memory, size);
1689ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
1699ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1709ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1719ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgPosixMemoryMappedFile::~PosixMemoryMappedFile() {
1729ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (memory_) OS::Free(memory_, size_);
1739ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  fclose(file_);
1749ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
1759ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1769ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1771845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.orgstd::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
1781845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  std::vector<SharedLibraryAddress> result;
1799ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  procfs_mapinfo *mapinfos = NULL, *mapinfo;
1809ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  int proc_fd, num, i;
1819ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1829ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  struct {
1839ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    procfs_debuginfo info;
1849ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    char buff[PATH_MAX];
1859ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  } map;
1869ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1879ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  char buf[PATH_MAX + 1];
1889ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  snprintf(buf, PATH_MAX + 1, "/proc/%d/as", getpid());
1899ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1909ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if ((proc_fd = open(buf, O_RDONLY)) == -1) {
1919ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    close(proc_fd);
1921845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return result;
1939ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
1949ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
1959ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  /* Get the number of map entries.  */
1969ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (devctl(proc_fd, DCMD_PROC_MAPINFO, NULL, 0, &num) != EOK) {
1979ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    close(proc_fd);
1981845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return result;
1999ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2009ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2019ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  mapinfos = reinterpret_cast<procfs_mapinfo *>(
2029ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      malloc(num * sizeof(procfs_mapinfo)));
2039ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (mapinfos == NULL) {
2049ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    close(proc_fd);
2051845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return result;
2069ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2079ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2089ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  /* Fill the map entries.  */
2099ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (devctl(proc_fd, DCMD_PROC_PAGEDATA,
2109ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      mapinfos, num * sizeof(procfs_mapinfo), &num) != EOK) {
2119ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    free(mapinfos);
2129ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    close(proc_fd);
2131845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    return result;
2149ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2159ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2169ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  for (i = 0; i < num; i++) {
2179ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    mapinfo = mapinfos + i;
2189ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    if (mapinfo->flags & MAP_ELF) {
2199ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      map.info.vaddr = mapinfo->vaddr;
2209ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      if (devctl(proc_fd, DCMD_PROC_MAPDEBUG, &map, sizeof(map), 0) != EOK) {
2219ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org        continue;
2229ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org      }
2231845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org      result.push_back(SharedLibraryAddress(
2241845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org          map.info.path, mapinfo->vaddr, mapinfo->vaddr + mapinfo->size));
2259ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    }
2269ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2279ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  free(mapinfos);
2289ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  close(proc_fd);
2291845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  return result;
2309ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
2319ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2329ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2339ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgvoid OS::SignalCodeMovingGC() {
2349ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
2359ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2369ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2379ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org// Constants used for mmap.
2389ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgstatic const int kMmapFd = -1;
2399ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgstatic const int kMmapFdOffset = 0;
2409ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2419ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2429ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
2439ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2449ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2459ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgVirtualMemory::VirtualMemory(size_t size)
2469ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    : address_(ReserveRegion(size)), size_(size) { }
2479ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2489ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2499ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgVirtualMemory::VirtualMemory(size_t size, size_t alignment)
2509ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    : address_(NULL), size_(0) {
2519ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
2529ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  size_t request_size = RoundUp(size + alignment,
2539ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                                static_cast<intptr_t>(OS::AllocateAlignment()));
2549ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* reservation = mmap(OS::GetRandomMmapAddr(),
2559ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                           request_size,
2569ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                           PROT_NONE,
2579ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                           MAP_PRIVATE | MAP_ANONYMOUS | MAP_LAZY,
2589ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                           kMmapFd,
2599ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                           kMmapFdOffset);
2609ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (reservation == MAP_FAILED) return;
2619ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2629ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  Address base = static_cast<Address>(reservation);
2639ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  Address aligned_base = RoundUp(base, alignment);
2649ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  ASSERT_LE(base, aligned_base);
2659ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2669ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  // Unmap extra memory reserved before and after the desired block.
2679ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (aligned_base != base) {
2689ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    size_t prefix_size = static_cast<size_t>(aligned_base - base);
2699ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    OS::Free(base, prefix_size);
2709ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    request_size -= prefix_size;
2719ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2729ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2739ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
2749ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  ASSERT_LE(aligned_size, request_size);
2759ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2769ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (aligned_size != request_size) {
2779ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    size_t suffix_size = request_size - aligned_size;
2789ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    OS::Free(aligned_base + aligned_size, suffix_size);
2799ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    request_size -= suffix_size;
2809ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2819ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2829ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  ASSERT(aligned_size == request_size);
2839ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2849ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  address_ = static_cast<void*>(aligned_base);
2859ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  size_ = aligned_size;
2869ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
2879ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2889ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2899ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgVirtualMemory::~VirtualMemory() {
2909ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (IsReserved()) {
2919ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    bool result = ReleaseRegion(address(), size());
2929ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    ASSERT(result);
2939ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    USE(result);
2949ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
2959ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
2969ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2979ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
2989ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::IsReserved() {
2999ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return address_ != NULL;
3009ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3019ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3029ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3039ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgvoid VirtualMemory::Reset() {
3049ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  address_ = NULL;
3059ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  size_ = 0;
3069ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3079ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3089ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3099ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
3109ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return CommitRegion(address, size, is_executable);
3119ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3129ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3139ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3149ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::Uncommit(void* address, size_t size) {
3159ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return UncommitRegion(address, size);
3169ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3179ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3189ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3199ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::Guard(void* address) {
3209ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  OS::Guard(address, OS::CommitPageSize());
3219ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return true;
3229ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3239ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3249ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3259ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgvoid* VirtualMemory::ReserveRegion(size_t size) {
3269ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  void* result = mmap(OS::GetRandomMmapAddr(),
3279ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                      size,
3289ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                      PROT_NONE,
3299ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_LAZY,
3309ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                      kMmapFd,
3319ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                      kMmapFdOffset);
3329ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3339ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (result == MAP_FAILED) return NULL;
3349ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3359ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return result;
3369ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3379ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3389ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3399ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
3409ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
3419ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  if (MAP_FAILED == mmap(base,
3429ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                         size,
3439ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                         prot,
3449ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
3459ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                         kMmapFd,
3469ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org                         kMmapFdOffset)) {
3479ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org    return false;
3489ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  }
3499ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3509ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return true;
3519ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3529ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3539ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3549ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::UncommitRegion(void* base, size_t size) {
3559ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return mmap(base,
3569ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org              size,
3579ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org              PROT_NONE,
3589ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org              MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_LAZY,
3599ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org              kMmapFd,
3609ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org              kMmapFdOffset) != MAP_FAILED;
3619ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3629ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3639ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3649ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::ReleaseRegion(void* base, size_t size) {
3659ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return munmap(base, size) == 0;
3669ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3679ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3689ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3699ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.orgbool VirtualMemory::HasLazyCommits() {
3709ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org  return false;
3719ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org}
3729ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
3739ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org} }  // namespace v8::internal
374