diff options
Diffstat (limited to 'V8Binding/v8/src/platform-freebsd.cc')
-rw-r--r-- | V8Binding/v8/src/platform-freebsd.cc | 645 |
1 files changed, 0 insertions, 645 deletions
diff --git a/V8Binding/v8/src/platform-freebsd.cc b/V8Binding/v8/src/platform-freebsd.cc deleted file mode 100644 index 73d6eeb..0000000 --- a/V8Binding/v8/src/platform-freebsd.cc +++ /dev/null @@ -1,645 +0,0 @@ -// 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 FreeBSD goes here. For the POSIX comaptible parts -// the implementation is in platform-posix.cc. - -#include <pthread.h> -#include <semaphore.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/types.h> -#include <sys/ucontext.h> -#include <stdlib.h> - -#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> -#include <limits.h> - -#undef MAP_TYPE - -#include "v8.h" - -#include "platform.h" - - -namespace v8 { -namespace internal { - -// 0 is never a valid thread id on FreeBSD since tids and pids share a -// name space and pid 0 is used to kill the group (see man 2 kill). -static const pthread_t kNoThread = (pthread_t) 0; - - -double ceiling(double x) { - // Correct as on OS X - if (-1.0 < x && x < 0.0) { - return -0.0; - } else { - 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)); -} - - -double OS::nan_value() { - return NAN; -} - - -int OS::ActivationFrameAlignment() { - // 16 byte alignment on FreeBSD - return 16; -} - - -// 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_ANON, -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. - int result = munmap(buf, length); - USE(result); - ASSERT(result == 0); -} - - -#ifdef ENABLE_HEAP_PROTECTION - -void OS::Protect(void* address, size_t size) { - UNIMPLEMENTED(); -} - - -void OS::Unprotect(void* address, size_t size, bool is_executable) { - UNIMPLEMENTED(); -} - -#endif - - -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_PROFILING -static unsigned StringToLong(char* buffer) { - return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT -} -#endif - - -void 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 = StringToLong(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 = StringToLong(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; - char* start_of_path = index(buffer, '/'); - // There may be no filename in this line. Skip to next. - if (start_of_path == NULL) continue; - buffer[bytes_read] = 0; - LOG(SharedLibraryEvent(start_of_path, start, end)); - } - close(fd); -#endif -} - - -int OS::StackWalk(Vector<OS::StackFrame> frames) { - int frames_size = frames.length(); - void** addresses = NewArray<void*>(frames_size); - - int frames_count = backtrace(addresses, frames_size); - - char** symbols; - symbols = backtrace_symbols(addresses, frames_count); - if (symbols == NULL) { - DeleteArray(addresses); - return kStackWalkError; - } - - for (int i = 0; i < frames_count; i++) { - frames[i].address = addresses[i]; - // Format a text representation of the frame based on the information - // available. - SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen), - "%s", - symbols[i]); - // Make sure line termination is in place. - frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; - } - - DeleteArray(addresses); - free(symbols); - - return frames_count; -} - - -// Constants used for mmap. -static const int kMmapFd = -1; -static const int kMmapFdOffset = 0; - - -VirtualMemory::VirtualMemory(size_t size) { - address_ = mmap(NULL, size, PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, - kMmapFd, kMmapFdOffset); - size_ = size; -} - - -VirtualMemory::~VirtualMemory() { - if (IsReserved()) { - if (0 == munmap(address(), size())) address_ = MAP_FAILED; - } -} - - -bool VirtualMemory::IsReserved() { - return address_ != MAP_FAILED; -} - - -bool VirtualMemory::Commit(void* address, size_t size, bool executable) { - int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0); - if (MAP_FAILED == mmap(address, size, prot, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, - kMmapFd, kMmapFdOffset)) { - return false; - } - - UpdateAllocatedSpaceLimits(address, size); - return true; -} - - -bool VirtualMemory::Uncommit(void* address, size_t size) { - return mmap(address, size, PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED, - kMmapFd, kMmapFdOffset) != MAP_FAILED; -} - - -class ThreadHandle::PlatformData : public Malloced { - public: - explicit PlatformData(ThreadHandle::Kind kind) { - Initialize(kind); - } - - void Initialize(ThreadHandle::Kind kind) { - switch (kind) { - case ThreadHandle::SELF: thread_ = pthread_self(); break; - case ThreadHandle::INVALID: thread_ = kNoThread; break; - } - } - pthread_t thread_; // Thread handle for pthread. -}; - - -ThreadHandle::ThreadHandle(Kind kind) { - data_ = new PlatformData(kind); -} - - -void ThreadHandle::Initialize(ThreadHandle::Kind kind) { - data_->Initialize(kind); -} - - -ThreadHandle::~ThreadHandle() { - delete data_; -} - - -bool ThreadHandle::IsSelf() const { - return pthread_equal(data_->thread_, pthread_self()); -} - - -bool ThreadHandle::IsValid() const { - return data_->thread_ != kNoThread; -} - - -Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { -} - - -Thread::~Thread() { -} - - -static void* ThreadEntry(void* arg) { - Thread* thread = reinterpret_cast<Thread*>(arg); - // This is also initialized by the first argument to pthread_create() but we - // don't know which thread will run first (the original thread or the new - // one) so we initialize it here too. - thread->thread_handle_data()->thread_ = pthread_self(); - ASSERT(thread->IsValid()); - thread->Run(); - return NULL; -} - - -void Thread::Start() { - pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this); - ASSERT(IsValid()); -} - - -void Thread::Join() { - pthread_join(thread_handle_data()->thread_, NULL); -} - - -Thread::LocalStorageKey Thread::CreateThreadLocalKey() { - pthread_key_t key; - int result = pthread_key_create(&key, NULL); - USE(result); - ASSERT(result == 0); - return static_cast<LocalStorageKey>(key); -} - - -void Thread::DeleteThreadLocalKey(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast<pthread_key_t>(key); - int result = pthread_key_delete(pthread_key); - USE(result); - ASSERT(result == 0); -} - - -void* Thread::GetThreadLocal(LocalStorageKey key) { - pthread_key_t pthread_key = static_cast<pthread_key_t>(key); - return pthread_getspecific(pthread_key); -} - - -void Thread::SetThreadLocal(LocalStorageKey key, void* value) { - pthread_key_t pthread_key = static_cast<pthread_key_t>(key); - pthread_setspecific(pthread_key, value); -} - - -void Thread::YieldCPU() { - sched_yield(); -} - - -class FreeBSDMutex : public Mutex { - public: - - FreeBSDMutex() { - pthread_mutexattr_t attrs; - int result = pthread_mutexattr_init(&attrs); - ASSERT(result == 0); - result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); - ASSERT(result == 0); - result = pthread_mutex_init(&mutex_, &attrs); - ASSERT(result == 0); - } - - virtual ~FreeBSDMutex() { pthread_mutex_destroy(&mutex_); } - - virtual int Lock() { - int result = pthread_mutex_lock(&mutex_); - return result; - } - - virtual int Unlock() { - int result = pthread_mutex_unlock(&mutex_); - return result; - } - - private: - pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. -}; - - -Mutex* OS::CreateMutex() { - return new FreeBSDMutex(); -} - - -class FreeBSDSemaphore : public Semaphore { - public: - explicit FreeBSDSemaphore(int count) { sem_init(&sem_, 0, count); } - virtual ~FreeBSDSemaphore() { sem_destroy(&sem_); } - - virtual void Wait(); - virtual bool Wait(int timeout); - virtual void Signal() { sem_post(&sem_); } - private: - sem_t sem_; -}; - - -void FreeBSDSemaphore::Wait() { - while (true) { - int result = sem_wait(&sem_); - if (result == 0) return; // Successfully got semaphore. - CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. - } -} - - -bool FreeBSDSemaphore::Wait(int timeout) { - const long kOneSecondMicros = 1000000; // NOLINT - - // Split timeout into second and nanosecond parts. - struct timeval delta; - delta.tv_usec = timeout % kOneSecondMicros; - delta.tv_sec = timeout / kOneSecondMicros; - - struct timeval current_time; - // Get the current time. - if (gettimeofday(¤t_time, NULL) == -1) { - return false; - } - - // Calculate time for end of timeout. - struct timeval end_time; - timeradd(¤t_time, &delta, &end_time); - - struct timespec ts; - TIMEVAL_TO_TIMESPEC(&end_time, &ts); - while (true) { - int result = sem_timedwait(&sem_, &ts); - if (result == 0) return true; // Successfully got semaphore. - if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. - CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. - } -} - - -Semaphore* OS::CreateSemaphore(int count) { - return new FreeBSDSemaphore(count); -} - - -#ifdef ENABLE_LOGGING_AND_PROFILING - -static Sampler* active_sampler_ = NULL; - -static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { - USE(info); - if (signal != SIGPROF) return; - if (active_sampler_ == NULL) return; - - TickSample sample; - - // If profiling, we extract the current pc and sp. - if (active_sampler_->IsProfiling()) { - // Extracting the sample from the context is extremely machine dependent. - ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); - mcontext_t& mcontext = ucontext->uc_mcontext; -#if V8_HOST_ARCH_IA32 - sample.pc = mcontext.mc_eip; - sample.sp = mcontext.mc_esp; - sample.fp = mcontext.mc_ebp; -#elif V8_HOST_ARCH_X64 - sample.pc = mcontext.mc_rip; - sample.sp = mcontext.mc_rsp; - sample.fp = mcontext.mc_rbp; -#elif V8_HOST_ARCH_ARM - sample.pc = mcontext.mc_r15; - sample.sp = mcontext.mc_r13; - sample.fp = mcontext.mc_r11; -#endif - active_sampler_->SampleStack(&sample); - } - - // We always sample the VM state. - sample.state = Logger::state(); - - active_sampler_->Tick(&sample); -} - - -class Sampler::PlatformData : public Malloced { - public: - PlatformData() { - signal_handler_installed_ = false; - } - - bool signal_handler_installed_; - struct sigaction old_signal_handler_; - struct itimerval old_timer_value_; -}; - - -Sampler::Sampler(int interval, bool profiling) - : interval_(interval), profiling_(profiling), active_(false) { - data_ = new PlatformData(); -} - - -Sampler::~Sampler() { - delete data_; -} - - -void Sampler::Start() { - // There can only be one active sampler at the time on POSIX - // platforms. - if (active_sampler_ != NULL) return; - - // Request profiling signals. - struct sigaction sa; - sa.sa_sigaction = ProfilerSignalHandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO; - if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; - data_->signal_handler_installed_ = true; - - // Set the itimer to generate a tick for each interval. - itimerval itimer; - itimer.it_interval.tv_sec = interval_ / 1000; - itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; - itimer.it_value.tv_sec = itimer.it_interval.tv_sec; - itimer.it_value.tv_usec = itimer.it_interval.tv_usec; - setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); - - // Set this sampler as the active sampler. - active_sampler_ = this; - active_ = true; -} - - -void Sampler::Stop() { - // Restore old signal handler - if (data_->signal_handler_installed_) { - setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL); - sigaction(SIGPROF, &data_->old_signal_handler_, 0); - data_->signal_handler_installed_ = false; - } - - // This sampler is no longer the active sampler. - active_sampler_ = NULL; - active_ = false; -} - -#endif // ENABLE_LOGGING_AND_PROFILING - -} } // namespace v8::internal |