// Copyright 2012 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 POSIX goes here. This is not a platform on its
-// own but contains the parts which are the same across POSIX platforms Linux,
-// Mac OS, FreeBSD and OpenBSD.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Platform-specific code for POSIX goes here. This is not a platform on its
+// own, but contains the parts which are the same across the POSIX platforms
+// Linux, MacOS, FreeBSD, OpenBSD, NetBSD and QNX.
#include <dlfcn.h>
#include <pthread.h>
struct rlimit limit;
int result = getrlimit(RLIMIT_DATA, &limit);
if (result != 0) return 0;
+#if V8_OS_NACL
+ // The NaCl compiler doesn't like resource.h constants.
+ if (static_cast<int>(limit.rlim_cur) == -1) return 0;
+#else
+ if (limit.rlim_cur == RLIM_INFINITY) return 0;
+#endif
return limit.rlim_cur;
}
return 0;
}
return static_cast<uint64_t>(memory_info.dwTotalPhys);
+#elif V8_OS_QNX
+ struct stat stat_buf;
+ if (stat("/proc", &stat_buf) != 0) {
+ UNREACHABLE();
+ return 0;
+ }
+ return static_cast<uint64_t>(stat_buf.st_size);
#else
intptr_t pages = sysconf(_SC_PHYS_PAGES);
intptr_t page_size = sysconf(_SC_PAGESIZE);
// Get rid of writable permission on code allocations.
void OS::ProtectCode(void* address, const size_t size) {
-#if defined(__CYGWIN__)
+#if V8_OS_CYGWIN
DWORD old_protect;
VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
-#elif defined(__native_client__)
+#elif V8_OS_NACL
// The Native Client port of V8 uses an interpreter, so
// code pages don't need PROT_EXEC.
mprotect(address, size, PROT_READ);
// Create guard pages.
void OS::Guard(void* address, const size_t size) {
-#if defined(__CYGWIN__)
+#if V8_OS_CYGWIN
DWORD oldprotect;
VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect);
#else
void* OS::GetRandomMmapAddr() {
-#if defined(__native_client__)
+#if V8_OS_NACL
// TODO(bradchen): restore randomization once Native Client gets
// smarter about using mmap address hints.
// See http://code.google.com/p/nativeclient/issues/3341
return NULL;
#endif
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
+ defined(THREAD_SANITIZER)
+ // Dynamic tools do not support custom mmap addresses.
+ return NULL;
+#endif
Isolate* isolate = Isolate::UncheckedCurrent();
// Note that the current isolate isn't set up in a call path via
// CpuFeatures::Probe. We don't care about randomization in this case because
size_t OS::AllocateAlignment() {
- return getpagesize();
+ return static_cast<size_t>(sysconf(_SC_PAGESIZE));
}
void OS::Abort() {
- // Redirect to std abort to signal abnormal program termination.
- if (FLAG_break_on_abort) {
- DebugBreak();
+ if (FLAG_hard_abort) {
+ V8_IMMEDIATE_CRASH();
}
+ // Redirect to std abort to signal abnormal program termination.
abort();
}
void OS::DebugBreak() {
#if V8_HOST_ARCH_ARM
asm("bkpt 0");
+#elif V8_HOST_ARCH_ARM64
+ asm("brk 0");
#elif V8_HOST_ARCH_MIPS
asm("break");
#elif V8_HOST_ARCH_IA32
// ----------------------------------------------------------------------------
// Math functions
-double ceiling(double x) {
- // Correct buggy 'ceil' on some systems (i.e. FreeBSD, OS X 10.5)
- return (-1.0 < x && x < 0.0) ? -0.0 : ceil(x);
-}
-
-
double modulo(double x, double y) {
- return fmod(x, y);
+ return std::fmod(x, y);
}
return (*fast_##name##_function)(x); \
}
-UNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN))
-UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS))
-UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN))
-UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG))
UNARY_MATH_FUNCTION(exp, CreateExpFunction())
UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
}
-double OS::DaylightSavingsOffset(double time) {
+class TimezoneCache {};
+
+
+TimezoneCache* OS::CreateTimezoneCache() {
+ return NULL;
+}
+
+
+void OS::DisposeTimezoneCache(TimezoneCache* cache) {
+ ASSERT(cache == NULL);
+}
+
+
+void OS::ClearTimezoneCache(TimezoneCache* cache) {
+ ASSERT(cache == NULL);
+}
+
+
+double OS::DaylightSavingsOffset(double time, TimezoneCache*) {
if (std::isnan(time)) return nan_value();
- 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 nan_value();
return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
#elif defined(V8_HOST_ARCH_ARM)
void OS::MemCopyUint16Uint8Wrapper(uint16_t* dest,
- const uint8_t* src,
- size_t chars) {
+ const uint8_t* src,
+ size_t chars) {
uint16_t *limit = dest + chars;
while (dest < limit) {
*dest++ = static_cast<uint16_t>(*src++);
OS::MemCopyUint8Function stub);
OS::MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
OS::MemCopyUint16Uint8Function stub);
+
+#elif defined(V8_HOST_ARCH_MIPS)
+OS::MemCopyUint8Function OS::memcopy_uint8_function = &OS::MemCopyUint8Wrapper;
+// Defined in codegen-mips.cc.
+OS::MemCopyUint8Function CreateMemCopyUint8Function(
+ OS::MemCopyUint8Function stub);
#endif
CreateMemCopyUint8Function(&OS::MemCopyUint8Wrapper);
OS::memcopy_uint16_uint8_function =
CreateMemCopyUint16Uint8Function(&OS::MemCopyUint16Uint8Wrapper);
+#elif defined(V8_HOST_ARCH_MIPS)
+ OS::memcopy_uint8_function =
+ CreateMemCopyUint8Function(&OS::MemCopyUint8Wrapper);
#endif
- init_fast_sin_function();
- init_fast_cos_function();
- init_fast_tan_function();
- init_fast_log_function();
// fast_exp is initialized lazily.
init_fast_sqrt_function();
}
public:
PlatformData() : thread_(kNoThread) {}
pthread_t thread_; // Thread handle for pthread.
+ // Synchronizes thread creation
+ Mutex thread_creation_mutex_;
};
Thread::Thread(const Options& options)
: data_(new PlatformData),
stack_size_(options.stack_size()),
start_semaphore_(NULL) {
+ if (stack_size_ > 0 && stack_size_ < PTHREAD_STACK_MIN) {
+ stack_size_ = PTHREAD_STACK_MIN;
+ }
set_name(options.name());
}
static void SetThreadName(const char* name) {
-#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+#if V8_OS_DRAGONFLYBSD || V8_OS_FREEBSD || V8_OS_OPENBSD
pthread_set_name_np(pthread_self(), name);
-#elif defined(__NetBSD__)
+#elif V8_OS_NETBSD
STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP);
pthread_setname_np(pthread_self(), "%s", name);
-#elif defined(__APPLE__)
+#elif V8_OS_MACOSX
// pthread_setname_np is only available in 10.6 or later, so test
// for it at runtime.
int (*dynamic_pthread_setname_np)(const char*);
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->data()->thread_ = pthread_self();
+ // We take the lock here to make sure that pthread_create finished first since
+ // we don't know which thread will run first (the original thread or the new
+ // one).
+ { LockGuard<Mutex> lock_guard(&thread->data()->thread_creation_mutex_); }
SetThreadName(thread->name());
ASSERT(thread->data()->thread_ != kNoThread);
thread->NotifyStartedAndRun();
result = pthread_attr_init(&attr);
ASSERT_EQ(0, result);
// Native client uses default stack size.
-#if !defined(__native_client__)
+#if !V8_OS_NACL
if (stack_size_ > 0) {
result = pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
ASSERT_EQ(0, result);
}
#endif
- result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
+ {
+ LockGuard<Mutex> lock_guard(&data_->thread_creation_mutex_);
+ result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
+ }
ASSERT_EQ(0, result);
result = pthread_attr_destroy(&attr);
ASSERT_EQ(0, result);
static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
-#if defined(__CYGWIN__)
+#if V8_OS_CYGWIN
// We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
// because pthread_key_t is a pointer type on Cygwin. This will probably not
// work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
-#if defined(__CYGWIN__)
+#if V8_OS_CYGWIN
STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
intptr_t ptr_key = static_cast<intptr_t>(local_key);
return reinterpret_cast<pthread_key_t>(ptr_key);