blob: 2ea6ef4a6ce30a66116b1ab2c71f31ca5a2a7794 [file] [log] [blame]
// Copyright 2012 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 Solaris 10 goes here. For the POSIX-compatible
// parts, the implementation is in platform-posix.cc.
#ifdef __sparc
# error "V8 does not support the SPARC CPU architecture."
#endif
#include <dlfcn.h> // dladdr
#include <errno.h>
#include <ieeefp.h> // finite()
#include <pthread.h>
#include <semaphore.h>
#include <signal.h> // sigemptyset(), etc
#include <sys/mman.h> // mmap()
#include <sys/regset.h>
#include <sys/stack.h> // for stack alignment
#include <sys/time.h> // gettimeofday(), timeradd()
#include <time.h>
#include <ucontext.h> // walkstack(), getcontext()
#include <unistd.h> // getpagesize(), usleep()
#include <cmath>
#undef MAP_TYPE
#include "src/base/macros.h"
#include "src/base/platform/platform-posix.h"
#include "src/base/platform/platform.h"
namespace v8 {
namespace base {
class SolarisTimezoneCache : public PosixTimezoneCache {
const char* LocalTimezone(double time) override;
double LocalTimeOffset() override;
~SolarisTimezoneCache() override {}
};
const char* SolarisTimezoneCache::LocalTimezone(double time) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm tm;
struct tm* t = localtime_r(&tv, &tm);
if (NULL == t) return "";
return tzname[0]; // The location of the timezone string on Solaris.
}
double SolarisTimezoneCache::LocalTimeOffset() {
tzset();
return -static_cast<double>(timezone * msPerSecond);
}
TimezoneCache* OS::CreateTimezoneCache() { return new SolarisTimezoneCache(); }
// Constants used for mmap.
static const int kMmapFd = -1;
static const int kMmapFdOffset = 0;
void* OS::Allocate(const size_t requested, size_t* allocated,
OS::MemoryPermission access, void* hint) {
const size_t msize = RoundUp(requested, getpagesize());
int prot = GetProtectionFromMemoryPermission(access);
void* mbase =
mmap(hint, msize, prot, MAP_PRIVATE | MAP_ANON, kMmapFd, kMmapFdOffset);
if (mbase == MAP_FAILED) return NULL;
*allocated = msize;
return mbase;
}
// static
void* OS::ReserveRegion(size_t size, void* hint) {
void* result =
mmap(hint, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
kMmapFd, kMmapFdOffset);
if (result == MAP_FAILED) return NULL;
return result;
}
// static
void* OS::ReserveAlignedRegion(size_t size, size_t alignment, void* hint,
size_t* allocated) {
DCHECK((alignment % OS::AllocateAlignment()) == 0);
hint = AlignedAddress(hint, alignment);
size_t request_size = RoundUp(size + alignment,
static_cast<intptr_t>(OS::AllocateAlignment()));
void* result = ReserveRegion(request_size, hint);
if (result == nullptr) {
*allocated = 0;
return nullptr;
}
uint8_t* base = static_cast<uint8_t*>(result);
uint8_t* aligned_base = RoundUp(base, alignment);
DCHECK_LE(base, aligned_base);
// Unmap extra memory reserved before and after the desired block.
if (aligned_base != base) {
size_t prefix_size = static_cast<size_t>(aligned_base - base);
OS::Free(base, prefix_size);
request_size -= prefix_size;
}
size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
DCHECK_LE(aligned_size, request_size);
if (aligned_size != request_size) {
size_t suffix_size = request_size - aligned_size;
OS::Free(aligned_base + aligned_size, suffix_size);
request_size -= suffix_size;
}
DCHECK(aligned_size == request_size);
*allocated = aligned_size;
return static_cast<void*>(aligned_base);
}
// static
bool OS::CommitRegion(void* address, size_t size, bool is_executable) {
int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
if (MAP_FAILED == mmap(address, size, prot,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, kMmapFd,
kMmapFdOffset)) {
return false;
}
return true;
}
// static
bool OS::UncommitRegion(void* address, size_t size) {
return mmap(address, size, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, kMmapFd,
kMmapFdOffset) != MAP_FAILED;
}
// static
bool OS::ReleaseRegion(void* address, size_t size) {
return munmap(address, size) == 0;
}
// static
bool OS::ReleasePartialRegion(void* address, size_t size) {
return munmap(address, size) == 0;
}
// static
bool OS::HasLazyCommits() {
// TODO(alph): implement for the platform.
return false;
}
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
return std::vector<SharedLibraryAddress>();
}
void OS::SignalCodeMovingGC(void* hint) {}
} // namespace base
} // namespace v8