Introduce Starboard platform
Starboard is the platform abstraction for Cobalt. This CL introduces all Cobalt changes in src/base/platform. The review was conducted mostly on: https://chromium-review.googlesource.com/c/v8/v8/+/2247918 See b/156155426 for background Tbr: mlippautz@chromium.org Change-Id: I6cd092304ba6485acd38e82aa2dc4505d7dfb0aa Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2346090 Commit-Queue: John Xu <johnx@google.com> Reviewed-by: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Cr-Commit-Position: refs/heads/master@{#69530}
This commit is contained in:
parent
89004d8cec
commit
acbb989b3e
@ -70,6 +70,7 @@
|
||||
// V8_OS_POSIX - POSIX compatible (mostly everything except Windows)
|
||||
// V8_OS_QNX - QNX Neutrino
|
||||
// V8_OS_SOLARIS - Sun Solaris and OpenSolaris
|
||||
// V8_OS_STARBOARD - Starboard (platform abstraction for Cobalt)
|
||||
// V8_OS_AIX - AIX
|
||||
// V8_OS_WIN - Microsoft Windows
|
||||
|
||||
@ -93,6 +94,8 @@
|
||||
#elif defined(__sun)
|
||||
# define V8_OS_POSIX 1
|
||||
# define V8_OS_SOLARIS 1
|
||||
#elif defined(STARBOARD)
|
||||
# define V8_OS_STARBOARD 1
|
||||
#elif defined(_AIX)
|
||||
#define V8_OS_POSIX 1
|
||||
#define V8_OS_AIX 1
|
||||
|
3
src/DEPS
3
src/DEPS
@ -52,7 +52,8 @@ include_rules = [
|
||||
"-src/libplatform",
|
||||
"-include/libplatform",
|
||||
"+builtins-generated",
|
||||
"+torque-generated"
|
||||
"+torque-generated",
|
||||
"+starboard",
|
||||
]
|
||||
|
||||
specific_include_rules = {
|
||||
|
@ -36,9 +36,25 @@
|
||||
#include "src/base/base-export.h"
|
||||
#include "src/base/build_config.h"
|
||||
|
||||
#if defined(V8_OS_STARBOARD)
|
||||
#include "starboard/atomic.h"
|
||||
|
||||
#if SB_API_VERSION < 10
|
||||
#error Your version of Starboard must support SbAtomic8 in order to use V8.
|
||||
#endif // SB_API_VERSION < 10
|
||||
#endif // V8_OS_STARBOARD
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
#ifdef V8_OS_STARBOARD
|
||||
using Atomic8 = SbAtomic8;
|
||||
using Atomic16 = int16_t;
|
||||
using Atomic32 = SbAtomic32;
|
||||
#if SB_IS_64_BIT
|
||||
using Atomic64 = SbAtomic64;
|
||||
#endif
|
||||
#else
|
||||
using Atomic8 = char;
|
||||
using Atomic16 = int16_t;
|
||||
using Atomic32 = int32_t;
|
||||
@ -51,10 +67,15 @@ using Atomic64 = int64_t;
|
||||
using Atomic64 = intptr_t;
|
||||
#endif // defined(__ILP32__)
|
||||
#endif // defined(V8_HOST_ARCH_64_BIT)
|
||||
#endif // V8_OS_STARBOARD
|
||||
|
||||
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
|
||||
// Atomic64 routines below, depending on your architecture.
|
||||
#if defined(V8_OS_STARBOARD)
|
||||
using AtomicWord = SbAtomicPtr;
|
||||
#else
|
||||
using AtomicWord = intptr_t;
|
||||
#endif
|
||||
|
||||
// Atomically execute:
|
||||
// result = *ptr;
|
||||
@ -126,7 +147,7 @@ Atomic64 Acquire_Load(volatile const Atomic64* ptr);
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
||||
#if defined(V8_OS_WIN)
|
||||
#if defined(V8_OS_WIN) || defined(V8_OS_STARBOARD)
|
||||
#include "src/base/atomicops_internals_std.h"
|
||||
#else
|
||||
// TODO(ulan): Switch to std version after performance regression with Wheezy
|
||||
|
@ -4,6 +4,10 @@
|
||||
|
||||
#include "src/base/cpu.h"
|
||||
|
||||
#if defined(STARBOARD)
|
||||
#include "starboard/cpu_features.h"
|
||||
#endif
|
||||
|
||||
#if V8_LIBC_MSVCRT
|
||||
#include <intrin.h> // __cpuid()
|
||||
#endif
|
||||
@ -347,6 +351,54 @@ static bool HasListItem(const char* list, const char* item) {
|
||||
#endif // V8_HOST_ARCH_ARM || V8_HOST_ARCH_ARM64 ||
|
||||
// V8_HOST_ARCH_MIPS || V8_HOST_ARCH_MIPS64
|
||||
|
||||
#if defined(STARBOARD)
|
||||
|
||||
bool CPU::StarboardDetectCPU() {
|
||||
#if (SB_API_VERSION >= 11)
|
||||
SbCPUFeatures features;
|
||||
if (!SbCPUFeaturesGet(&features)) {
|
||||
return false;
|
||||
}
|
||||
architecture_ = features.arm.architecture_generation;
|
||||
switch (features.architecture) {
|
||||
case kSbCPUFeaturesArchitectureArm:
|
||||
case kSbCPUFeaturesArchitectureArm64:
|
||||
has_neon_ = features.arm.has_neon;
|
||||
has_thumb2_ = features.arm.has_thumb2;
|
||||
has_vfp_ = features.arm.has_vfp;
|
||||
has_vfp3_ = features.arm.has_vfp3;
|
||||
has_vfp3_d32_ = features.arm.has_vfp3_d32;
|
||||
has_idiva_ = features.arm.has_idiva;
|
||||
break;
|
||||
case kSbCPUFeaturesArchitectureX86:
|
||||
case kSbCPUFeaturesArchitectureX86_64:
|
||||
// Following flags are mandatory for V8
|
||||
has_cmov_ = features.x86.has_cmov;
|
||||
has_sse2_ = features.x86.has_sse2;
|
||||
// These flags are optional
|
||||
has_sse3_ = features.x86.has_sse3;
|
||||
has_ssse3_ = features.x86.has_ssse3;
|
||||
has_sse41_ = features.x86.has_sse41;
|
||||
has_sahf_ = features.x86.has_sahf;
|
||||
has_avx_ = features.x86.has_avx;
|
||||
has_fma3_ = features.x86.has_fma3;
|
||||
has_bmi1_ = features.x86.has_bmi1;
|
||||
has_bmi2_ = features.x86.has_bmi2;
|
||||
has_lzcnt_ = features.x86.has_lzcnt;
|
||||
has_popcnt_ = features.x86.has_popcnt;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else // SB_API_VERSION >= 11
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CPU::CPU()
|
||||
: stepping_(0),
|
||||
model_(0),
|
||||
@ -389,6 +441,13 @@ CPU::CPU()
|
||||
has_non_stop_time_stamp_counter_(false),
|
||||
has_msa_(false) {
|
||||
memcpy(vendor_, "Unknown", 8);
|
||||
|
||||
#if defined(STARBOARD)
|
||||
if (StarboardDetectCPU()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
|
||||
int cpu_info[4];
|
||||
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(V8_OS_STARBOARD)
|
||||
#include "starboard/thread.h"
|
||||
#else
|
||||
#include <sched.h>
|
||||
#endif
|
||||
@ -40,6 +42,8 @@ void CallOnceImpl(OnceType* once, std::function<void()> init_func) {
|
||||
ONCE_STATE_EXECUTING_FUNCTION) {
|
||||
#ifdef _WIN32
|
||||
::Sleep(0);
|
||||
#elif defined(V8_OS_STARBOARD)
|
||||
SbThreadYield();
|
||||
#else
|
||||
sched_yield();
|
||||
#endif
|
||||
|
@ -159,7 +159,37 @@ bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
#endif // V8_OS_POSIX
|
||||
#elif V8_OS_STARBOARD
|
||||
|
||||
ConditionVariable::ConditionVariable() {
|
||||
SbConditionVariableCreate(&native_handle_, nullptr);
|
||||
}
|
||||
|
||||
ConditionVariable::~ConditionVariable() {
|
||||
SbConditionVariableDestroy(&native_handle_);
|
||||
}
|
||||
|
||||
void ConditionVariable::NotifyOne() {
|
||||
SbConditionVariableSignal(&native_handle_);
|
||||
}
|
||||
|
||||
void ConditionVariable::NotifyAll() {
|
||||
SbConditionVariableBroadcast(&native_handle_);
|
||||
}
|
||||
|
||||
void ConditionVariable::Wait(Mutex* mutex) {
|
||||
SbConditionVariableWait(&native_handle_, &mutex->native_handle());
|
||||
}
|
||||
|
||||
bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
|
||||
SbTime microseconds = static_cast<SbTime>(rel_time.InMicroseconds());
|
||||
SbConditionVariableResult result = SbConditionVariableWaitTimed(
|
||||
&native_handle_, &mutex->native_handle(), microseconds);
|
||||
DCHECK(result != kSbConditionVariableFailed);
|
||||
return result == kSbConditionVariableSignaled;
|
||||
}
|
||||
|
||||
#endif // V8_OS_STARBOARD
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
@ -9,6 +9,10 @@
|
||||
#include "src/base/lazy-instance.h"
|
||||
#include "src/base/platform/mutex.h"
|
||||
|
||||
#if V8_OS_STARBOARD
|
||||
#include "starboard/common/condition_variable.h"
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
@ -64,6 +68,8 @@ class V8_BASE_EXPORT ConditionVariable final {
|
||||
using NativeHandle = pthread_cond_t;
|
||||
#elif V8_OS_WIN
|
||||
using NativeHandle = CONDITION_VARIABLE;
|
||||
#elif V8_OS_STARBOARD
|
||||
using NativeHandle = SbConditionVariable;
|
||||
#endif
|
||||
|
||||
NativeHandle& native_handle() {
|
||||
|
@ -294,7 +294,42 @@ bool SharedMutex::TryLockExclusive() {
|
||||
return TryAcquireSRWLockExclusive(&native_handle_);
|
||||
}
|
||||
|
||||
#endif // V8_OS_POSIX
|
||||
#elif V8_OS_STARBOARD
|
||||
|
||||
Mutex::Mutex() { SbMutexCreate(&native_handle_); }
|
||||
|
||||
Mutex::~Mutex() { SbMutexDestroy(&native_handle_); }
|
||||
|
||||
void Mutex::Lock() { SbMutexAcquire(&native_handle_); }
|
||||
|
||||
void Mutex::Unlock() { SbMutexRelease(&native_handle_); }
|
||||
|
||||
RecursiveMutex::RecursiveMutex() {}
|
||||
|
||||
RecursiveMutex::~RecursiveMutex() {}
|
||||
|
||||
void RecursiveMutex::Lock() { native_handle_.Acquire(); }
|
||||
|
||||
void RecursiveMutex::Unlock() { native_handle_.Release(); }
|
||||
|
||||
bool RecursiveMutex::TryLock() { return native_handle_.AcquireTry(); }
|
||||
|
||||
SharedMutex::SharedMutex() = default;
|
||||
|
||||
SharedMutex::~SharedMutex() = default;
|
||||
|
||||
void SharedMutex::LockShared() { native_handle_.AcquireReadLock(); }
|
||||
|
||||
void SharedMutex::LockExclusive() { native_handle_.AcquireWriteLock(); }
|
||||
|
||||
void SharedMutex::UnlockShared() { native_handle_.ReleaseReadLock(); }
|
||||
|
||||
void SharedMutex::UnlockExclusive() { native_handle_.ReleaseWriteLock(); }
|
||||
|
||||
bool SharedMutex::TryLockShared() { return false; }
|
||||
|
||||
bool SharedMutex::TryLockExclusive() { return false; }
|
||||
#endif // V8_OS_STARBOARD
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
||||
|
@ -16,6 +16,12 @@
|
||||
#include <pthread.h> // NOLINT
|
||||
#endif
|
||||
|
||||
#if V8_OS_STARBOARD
|
||||
#include "starboard/common/mutex.h"
|
||||
#include "starboard/common/recursive_mutex.h"
|
||||
#include "starboard/common/rwlock.h"
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
@ -58,6 +64,8 @@ class V8_BASE_EXPORT Mutex final {
|
||||
using NativeHandle = pthread_mutex_t;
|
||||
#elif V8_OS_WIN
|
||||
using NativeHandle = SRWLOCK;
|
||||
#elif V8_OS_STARBOARD
|
||||
using NativeHandle = SbMutex;
|
||||
#endif
|
||||
|
||||
NativeHandle& native_handle() {
|
||||
@ -159,6 +167,8 @@ class V8_BASE_EXPORT RecursiveMutex final {
|
||||
using NativeHandle = pthread_mutex_t;
|
||||
#elif V8_OS_WIN
|
||||
using NativeHandle = CRITICAL_SECTION;
|
||||
#elif V8_OS_STARBOARD
|
||||
using NativeHandle = starboard::RecursiveMutex;
|
||||
#endif
|
||||
|
||||
NativeHandle native_handle_;
|
||||
@ -247,6 +257,8 @@ class V8_BASE_EXPORT SharedMutex final {
|
||||
using NativeHandle = pthread_rwlock_t;
|
||||
#elif V8_OS_WIN
|
||||
using NativeHandle = SRWLOCK;
|
||||
#elif V8_OS_STARBOARD
|
||||
using NativeHandle = starboard::RWLock;
|
||||
#endif
|
||||
|
||||
NativeHandle native_handle_;
|
||||
|
500
src/base/platform/platform-starboard.cc
Normal file
500
src/base/platform/platform-starboard.cc
Normal file
@ -0,0 +1,500 @@
|
||||
// Copyright 2020 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Platform-specific code for Starboard goes here. Starboard is the platform
|
||||
// abstraction layer for Cobalt, an HTML5 container used mainly by YouTube
|
||||
// LivingRoom products. Starboard was ported to platforms like PlayStations,
|
||||
// AndroidTV, AppleTV, Samsung smart TVs and so on.
|
||||
|
||||
#include "src/base/lazy-instance.h"
|
||||
#include "src/base/macros.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
#include "src/base/platform/time.h"
|
||||
#include "src/base/timezone-cache.h"
|
||||
#include "src/base/utils/random-number-generator.h"
|
||||
#include "starboard/common/condition_variable.h"
|
||||
#include "starboard/common/log.h"
|
||||
#include "starboard/common/string.h"
|
||||
#include "starboard/configuration.h"
|
||||
#include "starboard/configuration_constants.h"
|
||||
#include "starboard/memory.h"
|
||||
#include "starboard/time.h"
|
||||
#include "starboard/time_zone.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
#ifdef __arm__
|
||||
bool OS::ArmUsingHardFloat() {
|
||||
// GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify
|
||||
// the Floating Point ABI used (PCS stands for Procedure Call Standard).
|
||||
// We use these as well as a couple of other defines to statically determine
|
||||
// what FP ABI used.
|
||||
// GCC versions 4.4 and below don't support hard-fp.
|
||||
// GCC versions 4.5 may support hard-fp without defining __ARM_PCS or
|
||||
// __ARM_PCS_VFP.
|
||||
|
||||
#define GCC_VERSION \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION >= 40600 && !defined(__clang__)
|
||||
#if defined(__ARM_PCS_VFP)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#elif GCC_VERSION < 40500 && !defined(__clang__)
|
||||
return false;
|
||||
|
||||
#else
|
||||
#if defined(__ARM_PCS_VFP)
|
||||
return true;
|
||||
#elif defined(__ARM_PCS) || defined(__SOFTFP__) || defined(__SOFTFP) || \
|
||||
!defined(__VFP_FP__)
|
||||
return false;
|
||||
#else
|
||||
#error \
|
||||
"Your version of compiler does not report the FP ABI compiled for." \
|
||||
"Please report it on this issue" \
|
||||
"http://code.google.com/p/v8/issues/detail?id=2140"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#undef GCC_VERSION
|
||||
}
|
||||
#endif // def __arm__
|
||||
|
||||
namespace {
|
||||
|
||||
static LazyInstance<RandomNumberGenerator>::type
|
||||
platform_random_number_generator = LAZY_INSTANCE_INITIALIZER;
|
||||
static LazyMutex rng_mutex = LAZY_MUTEX_INITIALIZER;
|
||||
|
||||
bool g_hard_abort = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
void OS::Initialize(bool hard_abort, const char* const gc_fake_mmap) {
|
||||
g_hard_abort = hard_abort;
|
||||
// This is only used on Posix, we don't need to use it for anything.
|
||||
}
|
||||
|
||||
int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
|
||||
#if SB_API_VERSION >= 12
|
||||
if (!SbTimeIsTimeThreadNowSupported()) return -1;
|
||||
#endif
|
||||
|
||||
#if SB_API_VERSION >= 12 || SB_HAS(TIME_THREAD_NOW)
|
||||
SbTimeMonotonic thread_now = SbTimeGetMonotonicThreadNow();
|
||||
*secs = thread_now / kSbTimeSecond;
|
||||
*usecs = thread_now % kSbTimeSecond;
|
||||
return 0;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
double OS::TimeCurrentMillis() { return Time::Now().ToJsTime(); }
|
||||
|
||||
int OS::ActivationFrameAlignment() {
|
||||
#if V8_TARGET_ARCH_ARM
|
||||
// On EABI ARM targets this is required for fp correctness in the
|
||||
// runtime system.
|
||||
return 8;
|
||||
#elif V8_TARGET_ARCH_MIPS
|
||||
return 8;
|
||||
#elif V8_TARGET_ARCH_S390
|
||||
return 8;
|
||||
#else
|
||||
// Otherwise we just assume 16 byte alignment, i.e.:
|
||||
// - With gcc 4.4 the tree vectorization optimizer can generate code
|
||||
// that requires 16 byte alignment such as movdqa on x86.
|
||||
// - Mac OS X, PPC and Solaris (64-bit) activation frames must
|
||||
// be 16 byte-aligned; see "Mac OS X ABI Function Call Guide"
|
||||
return 16;
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
size_t OS::AllocatePageSize() { return kSbMemoryPageSize; }
|
||||
|
||||
// static
|
||||
size_t OS::CommitPageSize() { return kSbMemoryPageSize; }
|
||||
|
||||
// static
|
||||
void OS::SetRandomMmapSeed(int64_t seed) { SB_NOTIMPLEMENTED(); }
|
||||
|
||||
// static
|
||||
void* OS::GetRandomMmapAddr() { return nullptr; }
|
||||
|
||||
void* Allocate(void* address, size_t size, OS::MemoryPermission access) {
|
||||
SbMemoryMapFlags sb_flags;
|
||||
switch (access) {
|
||||
case OS::MemoryPermission::kNoAccess:
|
||||
sb_flags = SbMemoryMapFlags(0);
|
||||
break;
|
||||
case OS::MemoryPermission::kReadWrite:
|
||||
sb_flags = SbMemoryMapFlags(kSbMemoryMapProtectReadWrite);
|
||||
break;
|
||||
default:
|
||||
SB_LOG(ERROR) << "The requested memory allocation access is not"
|
||||
" implemented for Starboard: "
|
||||
<< static_cast<int>(access);
|
||||
return nullptr;
|
||||
}
|
||||
void* result = SbMemoryMap(size, sb_flags, "v8::Base::Allocate");
|
||||
if (result == SB_MEMORY_MAP_FAILED) {
|
||||
return nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// The following code was taken from old v8 to deal with rounding up pointers.
|
||||
namespace {
|
||||
// Compute the 0-relative offset of some absolute value x of type T.
|
||||
// This allows conversion of Addresses and integral types into
|
||||
// 0-relative int offsets.
|
||||
template <typename T>
|
||||
constexpr inline intptr_t OffsetFrom(T x) {
|
||||
return x - static_cast<T>(0);
|
||||
}
|
||||
|
||||
// Compute the absolute value of type T for some 0-relative offset x.
|
||||
// This allows conversion of 0-relative int offsets into Addresses and
|
||||
// integral types.
|
||||
template <typename T>
|
||||
constexpr inline T AddressFrom(intptr_t x) {
|
||||
return static_cast<T>(static_cast<T>(0) + x);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T RoundDown(T x, intptr_t m) {
|
||||
// m must be a power of two.
|
||||
DCHECK(m != 0 && ((m & (m - 1)) == 0));
|
||||
return AddressFrom<T>(OffsetFrom(x) & -m);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T RoundUpOld(T x, intptr_t m) {
|
||||
return RoundDown<T>(static_cast<T>(x + m - 1), m);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void* OS::Allocate(void* address, size_t size, size_t alignment,
|
||||
MemoryPermission access) {
|
||||
size_t page_size = AllocatePageSize();
|
||||
DCHECK_EQ(0, size % page_size);
|
||||
DCHECK_EQ(0, alignment % page_size);
|
||||
address = AlignedAddress(address, alignment);
|
||||
// Add the maximum misalignment so we are guaranteed an aligned base address.
|
||||
size_t request_size = size + (alignment - page_size);
|
||||
request_size = RoundUp(request_size, OS::AllocatePageSize());
|
||||
void* result = base::Allocate(address, request_size, access);
|
||||
if (result == nullptr) return nullptr;
|
||||
|
||||
// Unmap memory allocated before the aligned base address.
|
||||
uint8_t* base = static_cast<uint8_t*>(result);
|
||||
uint8_t* aligned_base = RoundUpOld(base, alignment);
|
||||
if (aligned_base != base) {
|
||||
DCHECK_LT(base, aligned_base);
|
||||
size_t prefix_size = static_cast<size_t>(aligned_base - base);
|
||||
CHECK(Free(base, prefix_size));
|
||||
request_size -= prefix_size;
|
||||
}
|
||||
// Unmap memory allocated after the potentially unaligned end.
|
||||
if (size != request_size) {
|
||||
DCHECK_LT(size, request_size);
|
||||
size_t suffix_size = request_size - size;
|
||||
CHECK(Free(aligned_base + size, suffix_size));
|
||||
request_size -= suffix_size;
|
||||
}
|
||||
|
||||
DCHECK_EQ(size, request_size);
|
||||
return static_cast<void*>(aligned_base);
|
||||
}
|
||||
|
||||
// static
|
||||
bool OS::Free(void* address, const size_t size) {
|
||||
return SbMemoryUnmap(address, size);
|
||||
}
|
||||
|
||||
// static
|
||||
bool OS::Release(void* address, size_t size) {
|
||||
return SbMemoryUnmap(address, size);
|
||||
}
|
||||
|
||||
// static
|
||||
bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) {
|
||||
SbMemoryMapFlags new_protection;
|
||||
switch (access) {
|
||||
case OS::MemoryPermission::kNoAccess:
|
||||
new_protection = SbMemoryMapFlags(0);
|
||||
break;
|
||||
case OS::MemoryPermission::kRead:
|
||||
new_protection = SbMemoryMapFlags(kSbMemoryMapProtectRead);
|
||||
case OS::MemoryPermission::kReadWrite:
|
||||
new_protection = SbMemoryMapFlags(kSbMemoryMapProtectReadWrite);
|
||||
break;
|
||||
case OS::MemoryPermission::kReadExecute:
|
||||
#if SB_CAN(MAP_EXECUTABLE_MEMORY)
|
||||
new_protection =
|
||||
SbMemoryMapFlags(kSbMemoryMapProtectRead | kSbMemoryMapProtectExec);
|
||||
#else
|
||||
UNREACHABLE();
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
// All other types are not supported by Starboard.
|
||||
return false;
|
||||
}
|
||||
return SbMemoryProtect(address, size, new_protection);
|
||||
}
|
||||
|
||||
// static
|
||||
bool OS::HasLazyCommits() {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
void OS::Sleep(TimeDelta interval) { SbThreadSleep(interval.InMicroseconds()); }
|
||||
|
||||
void OS::Abort() { SbSystemBreakIntoDebugger(); }
|
||||
|
||||
void OS::DebugBreak() { SbSystemBreakIntoDebugger(); }
|
||||
|
||||
class StarboardMemoryMappedFile final : public OS::MemoryMappedFile {
|
||||
public:
|
||||
~StarboardMemoryMappedFile() final;
|
||||
void* memory() const final {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
size_t size() const final {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return 0u;
|
||||
}
|
||||
};
|
||||
|
||||
// static
|
||||
OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name,
|
||||
FileMode mode) {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name,
|
||||
size_t size, void* initial) {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StarboardMemoryMappedFile::~StarboardMemoryMappedFile() { SB_NOTIMPLEMENTED(); }
|
||||
|
||||
int OS::GetCurrentProcessId() {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int OS::GetCurrentThreadId() { return SbThreadGetId(); }
|
||||
|
||||
int OS::GetLastError() { return SbSystemGetLastError(); }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// POSIX stdio support.
|
||||
//
|
||||
|
||||
FILE* OS::FOpen(const char* path, const char* mode) {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool OS::Remove(const char* path) {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
char OS::DirectorySeparator() { return kSbFileSepChar; }
|
||||
|
||||
bool OS::isDirectorySeparator(const char ch) {
|
||||
return ch == DirectorySeparator();
|
||||
}
|
||||
|
||||
FILE* OS::OpenTemporaryFile() {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* const OS::LogFileOpenMode = "\0";
|
||||
|
||||
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) {
|
||||
SbLogRawFormat(format, args);
|
||||
}
|
||||
|
||||
void OS::FPrint(FILE* out, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VPrintError(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void OS::VFPrint(FILE* out, const char* format, va_list args) {
|
||||
SbLogRawFormat(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) {
|
||||
// Starboard has no concept of stderr vs stdout.
|
||||
SbLogRawFormat(format, args);
|
||||
}
|
||||
|
||||
int OS::SNPrintF(char* str, int length, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int result = VSNPrintF(str, length, format, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
int OS::VSNPrintF(char* str, int length, const char* format, va_list args) {
|
||||
int n = SbStringFormat(str, length, format, args);
|
||||
if (n < 0 || n >= length) {
|
||||
// If the length is zero, the assignment fails.
|
||||
if (length > 0) str[length - 1] = '\0';
|
||||
return -1;
|
||||
} else {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// POSIX string support.
|
||||
//
|
||||
|
||||
void OS::StrNCpy(char* dest, int length, const char* src, size_t n) {
|
||||
SbStringCopy(dest, src, n);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// POSIX thread support.
|
||||
//
|
||||
|
||||
class Thread::PlatformData {
|
||||
public:
|
||||
PlatformData() : thread_(kSbThreadInvalid) {}
|
||||
SbThread 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_(nullptr) {
|
||||
set_name(options.name());
|
||||
}
|
||||
|
||||
Thread::~Thread() { delete data_; }
|
||||
|
||||
static void SetThreadName(const char* name) { SbThreadSetName(name); }
|
||||
|
||||
static void* ThreadEntry(void* arg) {
|
||||
Thread* thread = reinterpret_cast<Thread*>(arg);
|
||||
// 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());
|
||||
// DCHECK_NE(thread->data()->thread_, kNoThread);
|
||||
thread->NotifyStartedAndRun();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Thread::set_name(const char* name) {
|
||||
strncpy(name_, name, sizeof(name_));
|
||||
name_[sizeof(name_) - 1] = '\0';
|
||||
}
|
||||
|
||||
void Thread::Start() {
|
||||
data_->thread_ =
|
||||
SbThreadCreate(stack_size_, kSbThreadNoPriority, kSbThreadNoAffinity,
|
||||
true, name_, ThreadEntry, this);
|
||||
}
|
||||
|
||||
void Thread::Join() { SbThreadJoin(data_->thread_, nullptr); }
|
||||
|
||||
Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
|
||||
return SbThreadCreateLocalKey(nullptr);
|
||||
}
|
||||
|
||||
void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
|
||||
SbThreadDestroyLocalKey(key);
|
||||
}
|
||||
|
||||
void* Thread::GetThreadLocal(LocalStorageKey key) {
|
||||
return SbThreadGetLocalValue(key);
|
||||
}
|
||||
|
||||
void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
|
||||
bool result = SbThreadSetLocalValue(key, value);
|
||||
DCHECK(result);
|
||||
}
|
||||
|
||||
class StarboardTimezoneCache : public TimezoneCache {
|
||||
public:
|
||||
double DaylightSavingsOffset(double time_ms) override { return 0.0; }
|
||||
void Clear(TimeZoneDetection time_zone_detection) override {}
|
||||
~StarboardTimezoneCache() override {}
|
||||
|
||||
protected:
|
||||
static const int msPerSecond = 1000;
|
||||
};
|
||||
|
||||
class StarboardDefaultTimezoneCache : public StarboardTimezoneCache {
|
||||
public:
|
||||
const char* LocalTimezone(double time_ms) override {
|
||||
return SbTimeZoneGetName();
|
||||
}
|
||||
double LocalTimeOffset(double time_ms, bool is_utc) override {
|
||||
return SbTimeZoneGetCurrent() * 60000.0;
|
||||
}
|
||||
|
||||
~StarboardDefaultTimezoneCache() override {}
|
||||
};
|
||||
|
||||
TimezoneCache* OS::CreateTimezoneCache() {
|
||||
return new StarboardDefaultTimezoneCache();
|
||||
}
|
||||
|
||||
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
|
||||
SB_NOTIMPLEMENTED();
|
||||
return {};
|
||||
}
|
||||
|
||||
void OS::SignalCodeMovingGC() { SB_NOTIMPLEMENTED(); }
|
||||
|
||||
void OS::AdjustSchedulingParams() {}
|
||||
|
||||
bool OS::DiscardSystemPages(void* address, size_t size) {
|
||||
// Starboard API does not support this function yet.
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace base
|
||||
} // namespace v8
|
@ -74,6 +74,9 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
|
||||
|
||||
#elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
|
||||
|
||||
// tvOS simulator does not use intptr_t as TLS key.
|
||||
#if !defined(V8_OS_STARBOARD) || !defined(TARGET_OS_SIMULATOR)
|
||||
|
||||
#define V8_FAST_TLS_SUPPORTED 1
|
||||
|
||||
extern V8_BASE_EXPORT intptr_t kMacTlsBaseOffset;
|
||||
@ -94,6 +97,8 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // !defined(V8_OS_STARBOARD) || !defined(TARGET_OS_SIMULATOR)
|
||||
|
||||
#endif
|
||||
|
||||
#endif // V8_NO_FAST_TLS
|
||||
@ -323,7 +328,11 @@ inline void EnsureConsoleOutput() {
|
||||
class V8_BASE_EXPORT Thread {
|
||||
public:
|
||||
// Opaque data type for thread-local storage keys.
|
||||
#if V8_OS_STARBOARD
|
||||
using LocalStorageKey = SbThreadLocalKey;
|
||||
#else
|
||||
using LocalStorageKey = int32_t;
|
||||
#endif
|
||||
|
||||
class Options {
|
||||
public:
|
||||
|
@ -157,6 +157,21 @@ bool Semaphore::WaitFor(const TimeDelta& rel_time) {
|
||||
}
|
||||
}
|
||||
|
||||
#elif V8_OS_STARBOARD
|
||||
|
||||
Semaphore::Semaphore(int count) : native_handle_(count) { DCHECK_GE(count, 0); }
|
||||
|
||||
Semaphore::~Semaphore() {}
|
||||
|
||||
void Semaphore::Signal() { native_handle_.Put(); }
|
||||
|
||||
void Semaphore::Wait() { native_handle_.Take(); }
|
||||
|
||||
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
|
||||
SbTime microseconds = rel_time.InMicroseconds();
|
||||
return native_handle_.TakeWait(microseconds);
|
||||
}
|
||||
|
||||
#endif // V8_OS_MACOSX
|
||||
|
||||
} // namespace base
|
||||
|
@ -17,6 +17,10 @@
|
||||
#include <semaphore.h> // NOLINT
|
||||
#endif
|
||||
|
||||
#if V8_OS_STARBOARD
|
||||
#include "starboard/common/semaphore.h"
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace base {
|
||||
|
||||
@ -55,6 +59,8 @@ class V8_BASE_EXPORT Semaphore final {
|
||||
using NativeHandle = sem_t;
|
||||
#elif V8_OS_WIN
|
||||
using NativeHandle = HANDLE;
|
||||
#elif V8_OS_STARBOARD
|
||||
using NativeHandle = starboard::Semaphore;
|
||||
#endif
|
||||
|
||||
NativeHandle& native_handle() {
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "src/base/logging.h"
|
||||
#include "src/base/platform/platform.h"
|
||||
|
||||
#if V8_OS_STARBOARD
|
||||
#include "starboard/time.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
#if V8_OS_MACOSX
|
||||
@ -449,7 +453,13 @@ struct timeval Time::ToTimeval() const {
|
||||
return tv;
|
||||
}
|
||||
|
||||
#endif // V8_OS_WIN
|
||||
#elif V8_OS_STARBOARD
|
||||
|
||||
Time Time::Now() { return Time(SbTimeToPosix(SbTimeGetNow())); }
|
||||
|
||||
Time Time::NowFromSystemTime() { return Now(); }
|
||||
|
||||
#endif // V8_OS_STARBOARD
|
||||
|
||||
// static
|
||||
TimeTicks TimeTicks::HighResolutionNow() {
|
||||
@ -717,6 +727,8 @@ TimeTicks TimeTicks::Now() {
|
||||
ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
|
||||
#elif V8_OS_POSIX
|
||||
ticks = ClockNow(CLOCK_MONOTONIC);
|
||||
#elif V8_OS_STARBOARD
|
||||
ticks = SbTimeGetMonotonicNow();
|
||||
#else
|
||||
#error platform does not implement TimeTicks::HighResolutionNow.
|
||||
#endif // V8_OS_MACOSX
|
||||
@ -740,7 +752,15 @@ bool TimeTicks::IsHighResolution() {
|
||||
|
||||
|
||||
bool ThreadTicks::IsSupported() {
|
||||
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
|
||||
#if V8_OS_STARBOARD
|
||||
#if SB_API_VERSION >= 12
|
||||
return SbTimeIsTimeThreadNowSupported();
|
||||
#elif SB_HAS(TIME_THREAD_NOW)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
|
||||
defined(V8_OS_MACOSX) || defined(V8_OS_ANDROID) || defined(V8_OS_SOLARIS)
|
||||
return true;
|
||||
#elif defined(V8_OS_WIN)
|
||||
@ -752,7 +772,17 @@ bool ThreadTicks::IsSupported() {
|
||||
|
||||
|
||||
ThreadTicks ThreadTicks::Now() {
|
||||
#if V8_OS_MACOSX
|
||||
#if V8_OS_STARBOARD
|
||||
#if SB_API_VERSION >= 12
|
||||
if (SbTimeIsTimeThreadNowSupported())
|
||||
return ThreadTicks(SbTimeGetMonotonicThreadNow());
|
||||
UNREACHABLE();
|
||||
#elif SB_HAS(TIME_THREAD_NOW)
|
||||
return ThreadTicks(SbTimeGetMonotonicThreadNow());
|
||||
#else
|
||||
UNREACHABLE();
|
||||
#endif
|
||||
#elif V8_OS_MACOSX
|
||||
return ThreadTicks(ComputeThreadTicks());
|
||||
#elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
|
||||
defined(V8_OS_ANDROID)
|
||||
|
Loading…
Reference in New Issue
Block a user