Index: src/platform-qnx.cc |
diff --git a/src/platform-linux.cc b/src/platform-qnx.cc |
similarity index 67% |
copy from src/platform-linux.cc |
copy to src/platform-qnx.cc |
index eb2d10b3f9d911b5d0fbd607766724d5fa203f8b..cd031e795648c69d5dc910761c6e7394f6b59793 100644 |
--- a/src/platform-linux.cc |
+++ b/src/platform-qnx.cc |
@@ -1,4 +1,4 @@ |
-// Copyright 2012 the V8 project authors. All rights reserved. |
+// Copyright 2013 the V8 project authors. All rights reserved. |
// Redistribution and use in source and binary forms, with or without |
// modification, are permitted provided that the following conditions are |
// met: |
@@ -25,22 +25,21 @@ |
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
-// Platform specific code for Linux goes here. For the POSIX comaptible parts |
-// the implementation is in platform-posix.cc. |
+// Platform-specific code for QNX goes here. For the POSIX-compatible |
+// parts the implementation is in platform-posix.cc. |
#include <pthread.h> |
#include <semaphore.h> |
#include <signal.h> |
-#include <sys/prctl.h> |
#include <sys/time.h> |
#include <sys/resource.h> |
-#include <sys/syscall.h> |
#include <sys/types.h> |
#include <stdlib.h> |
+#include <ucontext.h> |
+#include <backtrace.h> |
-// Ubuntu Dapper requires memory pages to be marked as |
-// executable. Otherwise, OS raises an exception when executing code |
-// in that page. |
+// QNX requires memory pages to be marked as executable. |
+// Otherwise, the OS raises an exception when executing code in that page. |
#include <sys/types.h> // mmap & munmap |
#include <sys/mman.h> // mmap & munmap |
#include <sys/stat.h> // open |
@@ -49,13 +48,7 @@ |
#include <strings.h> // index |
#include <errno.h> |
#include <stdarg.h> |
- |
-// GLibc on ARM defines mcontext_t has a typedef for 'struct sigcontext'. |
-// Old versions of the C library <signal.h> didn't define the type. |
-#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) && \ |
- defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) |
-#include <asm/sigcontext.h> |
-#endif |
+#include <sys/procfs.h> |
#undef MAP_TYPE |
@@ -69,6 +62,10 @@ |
namespace v8 { |
namespace internal { |
+// 0 is never a valid thread id on Qnx since tids and pids share a |
+// name space and pid 0 is reserved (see man 2 kill). |
+static const pthread_t kNoThread = (pthread_t) 0; |
+ |
#ifdef __arm__ |
@@ -110,12 +107,12 @@ bool OS::ArmUsingHardFloat() { |
#undef GCC_VERSION |
} |
-#endif // def __arm__ |
+#endif // __arm__ |
const char* OS::LocalTimezone(double time) { |
if (std::isnan(time)) return ""; |
- time_t tv = static_cast<time_t>(floor(time/msPerSecond)); |
+ time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); |
struct tm* t = localtime(&tv); |
if (NULL == t) return ""; |
return t->tm_zone; |
@@ -207,95 +204,61 @@ PosixMemoryMappedFile::~PosixMemoryMappedFile() { |
void OS::LogSharedLibraryAddresses(Isolate* isolate) { |
- // This function assumes that the layout of the file is as follows: |
- // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] |
- // If we encounter an unexpected situation we abort scanning further entries. |
- FILE* fp = fopen("/proc/self/maps", "r"); |
- if (fp == NULL) return; |
- |
- // Allocate enough room to be able to store a full file name. |
- const int kLibNameLen = FILENAME_MAX + 1; |
- char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); |
- |
- // This loop will terminate once the scanning hits an EOF. |
- while (true) { |
- uintptr_t start, end; |
- char attr_r, attr_w, attr_x, attr_p; |
- // Parse the addresses and permission bits at the beginning of the line. |
- if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; |
- if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; |
- |
- int c; |
- if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { |
- // Found a read-only executable entry. Skip characters until we reach |
- // the beginning of the filename or the end of the line. |
- do { |
- c = getc(fp); |
- } while ((c != EOF) && (c != '\n') && (c != '/') && (c != '[')); |
- if (c == EOF) break; // EOF: Was unexpected, just exit. |
- |
- // Process the filename if found. |
- if ((c == '/') || (c == '[')) { |
- // Push the '/' or '[' back into the stream to be read below. |
- ungetc(c, fp); |
- |
- // Read to the end of the line. Exit if the read fails. |
- if (fgets(lib_name, kLibNameLen, fp) == NULL) break; |
- |
- // Drop the newline character read by fgets. We do not need to check |
- // for a zero-length string because we know that we at least read the |
- // '/' or '[' character. |
- lib_name[strlen(lib_name) - 1] = '\0'; |
- } else { |
- // No library name found, just record the raw address range. |
- snprintf(lib_name, kLibNameLen, |
- "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); |
+ procfs_mapinfo *mapinfos = NULL, *mapinfo; |
+ int proc_fd, num, i; |
+ |
+ struct { |
+ procfs_debuginfo info; |
+ char buff[PATH_MAX]; |
+ } map; |
+ |
+ char buf[PATH_MAX + 1]; |
+ snprintf(buf, PATH_MAX + 1, "/proc/%d/as", getpid()); |
+ |
+ if ((proc_fd = open(buf, O_RDONLY)) == -1) { |
+ close(proc_fd); |
+ return; |
+ } |
+ |
+ /* Get the number of map entries. */ |
+ if (devctl(proc_fd, DCMD_PROC_MAPINFO, NULL, 0, &num) != EOK) { |
+ close(proc_fd); |
+ return; |
+ } |
+ |
+ mapinfos = reinterpret_cast<procfs_mapinfo *>( |
+ malloc(num * sizeof(procfs_mapinfo))); |
+ if (mapinfos == NULL) { |
+ close(proc_fd); |
+ return; |
+ } |
+ |
+ /* Fill the map entries. */ |
+ if (devctl(proc_fd, DCMD_PROC_PAGEDATA, |
+ mapinfos, num * sizeof(procfs_mapinfo), &num) != EOK) { |
+ free(mapinfos); |
+ close(proc_fd); |
+ return; |
+ } |
+ |
+ for (i = 0; i < num; i++) { |
+ mapinfo = mapinfos + i; |
+ if (mapinfo->flags & MAP_ELF) { |
+ map.info.vaddr = mapinfo->vaddr; |
+ if (devctl(proc_fd, DCMD_PROC_MAPDEBUG, &map, sizeof(map), 0) != EOK) { |
+ continue; |
} |
- LOG(isolate, SharedLibraryEvent(lib_name, start, end)); |
- } else { |
- // Entry not describing executable data. Skip to end of line to set up |
- // reading the next entry. |
- do { |
- c = getc(fp); |
- } while ((c != EOF) && (c != '\n')); |
- if (c == EOF) break; |
+ LOG(isolate, SharedLibraryEvent(map.info.path, |
+ mapinfo->vaddr, |
+ mapinfo->vaddr + mapinfo->size)); |
} |
} |
- free(lib_name); |
- fclose(fp); |
+ free(mapinfos); |
+ close(proc_fd); |
} |
void OS::SignalCodeMovingGC() { |
- // Support for ll_prof.py. |
- // |
- // The Linux profiler built into the kernel logs all mmap's with |
- // PROT_EXEC so that analysis tools can properly attribute ticks. We |
- // do a mmap with a name known by ll_prof.py and immediately munmap |
- // it. This injects a GC marker into the stream of events generated |
- // by the kernel and allows us to synchronize V8 code log and the |
- // kernel log. |
- int size = sysconf(_SC_PAGESIZE); |
- FILE* f = fopen(FLAG_gc_fake_mmap, "w+"); |
- if (f == NULL) { |
- OS::PrintError("Failed to open %s\n", FLAG_gc_fake_mmap); |
- OS::Abort(); |
- } |
- void* addr = mmap(OS::GetRandomMmapAddr(), |
- size, |
-#if defined(__native_client__) |
- // The Native Client port of V8 uses an interpreter, |
- // so code pages don't need PROT_EXEC. |
- PROT_READ, |
-#else |
- PROT_READ | PROT_EXEC, |
-#endif |
- MAP_PRIVATE, |
- fileno(f), |
- 0); |
- ASSERT(addr != MAP_FAILED); |
- OS::Free(addr, size); |
- fclose(f); |
} |
@@ -319,7 +282,7 @@ VirtualMemory::VirtualMemory(size_t size, size_t alignment) |
void* reservation = mmap(OS::GetRandomMmapAddr(), |
request_size, |
PROT_NONE, |
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, |
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_LAZY, |
kMmapFd, |
kMmapFdOffset); |
if (reservation == MAP_FAILED) return; |
@@ -391,7 +354,7 @@ void* VirtualMemory::ReserveRegion(size_t size) { |
void* result = mmap(OS::GetRandomMmapAddr(), |
size, |
PROT_NONE, |
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, |
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_LAZY, |
kMmapFd, |
kMmapFdOffset); |
@@ -402,13 +365,7 @@ void* VirtualMemory::ReserveRegion(size_t size) { |
bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { |
-#if defined(__native_client__) |
- // The Native Client port of V8 uses an interpreter, |
- // so code pages don't need PROT_EXEC. |
- int prot = PROT_READ | PROT_WRITE; |
-#else |
int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); |
-#endif |
if (MAP_FAILED == mmap(base, |
size, |
prot, |
@@ -426,7 +383,7 @@ bool VirtualMemory::UncommitRegion(void* base, size_t size) { |
return mmap(base, |
size, |
PROT_NONE, |
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, |
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_LAZY, |
kMmapFd, |
kMmapFdOffset) != MAP_FAILED; |
} |
@@ -438,7 +395,7 @@ bool VirtualMemory::ReleaseRegion(void* base, size_t size) { |
bool VirtualMemory::HasLazyCommits() { |
- return true; |
+ return false; |
} |
} } // namespace v8::internal |