📄 platform-linux.cc.svn-base
字号:
// Copyright 2006-2008 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://// * Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// * Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following// disclaimer in the documentation and/or other materials provided// with the distribution.// * Neither the name of Google Inc. nor the names of its// contributors may be used to endorse or promote products derived// from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (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#include <pthread.h>#include <semaphore.h>#include <signal.h>#include <sys/time.h>#include <sys/resource.h>#include <stdlib.h>// Ubuntu Dapper requires memory pages to be marked as// executable. Otherwise, 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#include <sys/fcntl.h> // open#include <unistd.h> // getpagesize#include <execinfo.h> // backtrace, backtrace_symbols#include <strings.h> // index#include <errno.h>#include <stdarg.h>#undef MAP_TYPE#include "v8.h"#include "platform.h"namespace v8 { namespace internal {// 0 is never a valid thread id on Linux 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;double ceiling(double x) { return ceil(x);}void OS::Setup() { // Seed the random number generator. // Convert the current time to a 64-bit integer first, before converting it // to an unsigned. Going directly can cause an overflow and the seed to be // set to all ones. The seed will be identical for different instances that // call this setup code within the same millisecond. uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); srandom(static_cast<unsigned int>(seed));}int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { struct rusage usage; if (getrusage(RUSAGE_SELF, &usage) < 0) return -1; *secs = usage.ru_utime.tv_sec; *usecs = usage.ru_utime.tv_usec; return 0;}double OS::TimeCurrentMillis() { struct timeval tv; if (gettimeofday(&tv, NULL) < 0) return 0.0; return (static_cast<double>(tv.tv_sec) * 1000) + (static_cast<double>(tv.tv_usec) / 1000);}int64_t OS::Ticks() { // Linux's gettimeofday has microsecond resolution. struct timeval tv; if (gettimeofday(&tv, NULL) < 0) return 0; return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;}char* OS::LocalTimezone(double time) { time_t tv = static_cast<time_t>(floor(time/msPerSecond)); struct tm* t = localtime(&tv); return const_cast<char*>(t->tm_zone);}double OS::DaylightSavingsOffset(double time) { time_t tv = static_cast<time_t>(floor(time/msPerSecond)); struct tm* t = localtime(&tv); return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;}double OS::LocalTimeOffset() { time_t tv = time(NULL); struct tm* t = localtime(&tv); // tm_gmtoff includes any daylight savings offset, so subtract it. return static_cast<double>(t->tm_gmtoff * msPerSecond - (t->tm_isdst > 0 ? 3600 * msPerSecond : 0));}FILE* OS::FOpen(const char* path, const char* mode) { return fopen(path, mode);}void OS::Print(const char* format, ...) { va_list args; va_start(args, format); VPrint(format, args); va_end(args);}void OS::VPrint(const char* format, va_list args) { vprintf(format, args);}void OS::PrintError(const char* format, ...) { va_list args; va_start(args, format); VPrintError(format, args); va_end(args);}void OS::VPrintError(const char* format, va_list args) { vfprintf(stderr, format, args);}int OS::SNPrintF(Vector<char> str, const char* format, ...) { va_list args; va_start(args, format); int result = VSNPrintF(str, format, args); va_end(args); return result;}int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) { int n = vsnprintf(str.start(), str.length(), format, args); if (n < 0 || n >= str.length()) { str[str.length() - 1] = '\0'; return -1; } else { return n; }}void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { strncpy(dest.start(), src, n);}void OS::WcsCpy(Vector<wchar_t> dest, const wchar_t* src) { wcscpy(dest.start(), src);}char *OS::StrDup(const char* str) { return strdup(str);}double OS::nan_value() { return NAN;}int OS::ActivationFrameAlignment() { // No constraint on Linux. return 0;}// We keep the lowest and highest addresses mapped as a quick way of// determining that pointers are outside the heap (used mostly in assertions// and verification). The estimate is conservative, ie, not all addresses in// 'allocated' space are actually allocated to our heap. The range is// [lowest, highest), inclusive on the low and and exclusive on the high end.static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);static void* highest_ever_allocated = reinterpret_cast<void*>(0);static void UpdateAllocatedSpaceLimits(void* address, int size) { lowest_ever_allocated = Min(lowest_ever_allocated, address); highest_ever_allocated = Max(highest_ever_allocated, reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));}bool OS::IsOutsideAllocatedSpace(void* address) { return address < lowest_ever_allocated || address >= highest_ever_allocated;}size_t OS::AllocateAlignment() { return getpagesize();}void* OS::Allocate(const size_t requested, size_t* allocated, bool executable) { const size_t msize = RoundUp(requested, getpagesize()); int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (mbase == MAP_FAILED) { LOG(StringEvent("OS::Allocate", "mmap failed")); return NULL; } *allocated = msize; UpdateAllocatedSpaceLimits(mbase, msize); return mbase;}void OS::Free(void* buf, const size_t length) { // TODO(1240712): munmap has a return value which is ignored here. munmap(buf, length);}void OS::Sleep(int milliseconds) { unsigned int ms = static_cast<unsigned int>(milliseconds); usleep(1000 * ms);}void OS::Abort() { // Redirect to std abort to signal abnormal program termination. abort();}void OS::DebugBreak() {#if defined (__arm__) || defined(__thumb__) asm("bkpt 0");#else asm("int $3");#endif}class PosixMemoryMappedFile : public OS::MemoryMappedFile { public: PosixMemoryMappedFile(FILE* file, void* memory, int size) : file_(file), memory_(memory), size_(size) { } virtual ~PosixMemoryMappedFile(); virtual void* memory() { return memory_; } private: FILE* file_; void* memory_; int size_;};OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, void* initial) { FILE* file = fopen(name, "w+"); if (file == NULL) return NULL; int result = fwrite(initial, size, 1, file); if (result < 1) { fclose(file); return NULL; } void* memory = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); return new PosixMemoryMappedFile(file, memory, size);}PosixMemoryMappedFile::~PosixMemoryMappedFile() { if (memory_) munmap(memory_, size_); fclose(file_);}#ifdef ENABLE_LOGGING_AND_PROFILINGstatic unsigned StringToLongLong(char* buffer) { return static_cast<unsigned>(strtoll(buffer, NULL, 16)); // NOLINT}#endifvoid OS::LogSharedLibraryAddresses() {#ifdef ENABLE_LOGGING_AND_PROFILING static const int MAP_LENGTH = 1024; int fd = open("/proc/self/maps", O_RDONLY); if (fd < 0) return; while (true) { char addr_buffer[11]; addr_buffer[0] = '0'; addr_buffer[1] = 'x'; addr_buffer[10] = 0; int result = read(fd, addr_buffer + 2, 8); if (result < 8) break; unsigned start = StringToLongLong(addr_buffer); result = read(fd, addr_buffer + 2, 1); if (result < 1) break; if (addr_buffer[2] != '-') break; result = read(fd, addr_buffer + 2, 8); if (result < 8) break; unsigned end = StringToLongLong(addr_buffer); char buffer[MAP_LENGTH]; int bytes_read = -1; do { bytes_read++; if (bytes_read >= MAP_LENGTH - 1) break; result = read(fd, buffer + bytes_read, 1); if (result < 1) break; } while (buffer[bytes_read] != '\n'); buffer[bytes_read] = 0; // Ignore mappings that are not executable. if (buffer[3] != 'x') continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -