Skip to content

Instantly share code, notes, and snippets.

@piscisaureus
Created February 10, 2011 03:06
Show Gist options
  • Select an option

  • Save piscisaureus/819841 to your computer and use it in GitHub Desktop.

Select an option

Save piscisaureus/819841 to your computer and use it in GitHub Desktop.
From 0f7e1b38a09ce5d09f304431d886622647ff0070 Mon Sep 17 00:00:00 2001
From: Bert Belder <[email protected]>
Date: Thu, 10 Feb 2011 04:02:59 +0100
Subject: [PATCH 1/1] V8 cygwin support
---
SConstruct | 5 +-
src/SConscript | 1 +
src/{platform-linux.cc => platform-cygwin.cc} | 260 +++----------------------
src/platform.h | 4 +
tools/utils.py | 2 +
5 files changed, 40 insertions(+), 232 deletions(-)
copy deps/v8/src/{platform-linux.cc => platform-cygwin.cc} (71%)
diff --git a/SConstruct b/SConstruct
index c999399..b2542fd 100644
--- a/SConstruct
+++ b/SConstruct
@@ -188,6 +188,9 @@ LIBRARY_FLAGS = {
'LIBPATH' : ['/usr/local/lib'],
'CCFLAGS': ['-ansi'],
},
+ 'os:cygwin': {
+ 'WARNINGFLAGS': ['-Werror'],
+ },
'os:win32': {
'CCFLAGS': ['-DWIN32'],
'CXXFLAGS': ['-DWIN32'],
@@ -691,7 +694,7 @@ SIMPLE_OPTIONS = {
'help': 'the toolchain to use (%s)' % TOOLCHAIN_GUESS
},
'os': {
- 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris'],
+ 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris', 'cygwin'],
'default': OS_GUESS,
'help': 'the os to build for (%s)' % OS_GUESS
},
diff --git a/src/SConscript b/src/SConscript
index 76ca2dc..e85f022 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -234,6 +234,7 @@ SOURCES = {
'os:android': ['platform-linux.cc', 'platform-posix.cc'],
'os:macos': ['platform-macos.cc', 'platform-posix.cc'],
'os:solaris': ['platform-solaris.cc', 'platform-posix.cc'],
+ 'os:cygwin': ['platform-cygwin.cc', 'platform-posix.cc'],
'os:nullos': ['platform-nullos.cc'],
'os:win32': ['platform-win32.cc'],
'mode:release': [],
diff --git a/src/platform-linux.cc b/src/platform-cygwin.cc
similarity index 71%
copy from src/platform-linux.cc
copy to src/platform-cygwin.cc
index 761ff7e..2516943 100644
--- a/src/platform-linux.cc
+++ b/src/platform-cygwin.cc
@@ -25,16 +25,14 @@
// (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. For the POSIX comaptible parts
+// Platform specific code for Cygwin 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/prctl.h>
#include <sys/time.h>
#include <sys/resource.h>
-#include <sys/syscall.h>
#include <sys/types.h>
#include <stdlib.h>
@@ -187,32 +185,27 @@ int OS::ActivationFrameAlignment() {
void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
-#if defined(V8_TARGET_ARCH_ARM) && defined(__arm__)
- // Only use on ARM hardware.
- MemoryBarrier();
-#else
__asm__ __volatile__("" : : : "memory");
// An x86 store acts as a release barrier.
-#endif
*ptr = value;
}
-
const char* OS::LocalTimezone(double time) {
if (isnan(time)) return "";
time_t tv = static_cast<time_t>(floor(time/msPerSecond));
struct tm* t = localtime(&tv);
if (NULL == t) return "";
- return t->tm_zone;
+ return tzname[0]; // The location of the timezone string on Cywin.
}
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));
+ // On Cygwin, struct tm does not contain a tm_gmtoff field.
+ time_t utc = time(NULL);
+ ASSERT(utc != -1);
+ struct tm* loc = localtime(&utc);
+ ASSERT(loc != NULL);
+ return static_cast<double>((mktime(loc) - utc) * msPerSecond);
}
@@ -246,7 +239,6 @@ size_t OS::AllocateAlignment() {
void* OS::Allocate(const size_t requested,
size_t* allocated,
bool is_executable) {
- // TODO(805): Port randomization of allocated executable memory to Linux.
const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -300,10 +292,9 @@ void OS::Abort() {
void OS::DebugBreak() {
// TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
// which is the architecture of generated code).
-#if (defined(__arm__) || defined(__thumb__))
-# if defined(CAN_USE_ARMV5_INSTRUCTIONS)
+#if (defined(__arm__) || defined(__thumb__)) && \
+ defined(CAN_USE_ARMV5_INSTRUCTIONS)
asm("bkpt 0");
-# endif
#elif defined(__mips__)
asm("break");
#else
@@ -421,27 +412,7 @@ void OS::LogSharedLibraryAddresses() {
}
-static const char kGCFakeMmap[] = "/tmp/__v8_gc__";
-
-
void OS::SignalCodeMovingGC() {
-#ifdef ENABLE_LOGGING_AND_PROFILING
- // Support for ll_prof.py.
- //
- // The Linux profiler built into the kernel logs all mmap's with
- // PROT_EXEC so that analysis tools can properly attribute ticks. We
- // do a mmap with a name known by ll_prof.py and immediately munmap
- // it. This injects a GC marker into the stream of events generated
- // by the kernel and allows us to synchronize V8 code log and the
- // kernel log.
- int size = sysconf(_SC_PAGESIZE);
- FILE* f = fopen(kGCFakeMmap, "w+");
- void* addr = mmap(NULL, size, PROT_READ | PROT_EXEC, MAP_PRIVATE,
- fileno(f), 0);
- ASSERT(addr != MAP_FAILED);
- munmap(addr, size);
- fclose(f);
-#endif
}
@@ -505,9 +476,8 @@ bool VirtualMemory::IsReserved() {
bool VirtualMemory::Commit(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)) {
+
+ if (mprotect(address, size, prot) != 0) {
return false;
}
@@ -518,7 +488,7 @@ bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
bool VirtualMemory::Uncommit(void* address, size_t size) {
return mmap(address, size, PROT_NONE,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, // | MAP_FIXED, - Cygwin doesn't have MAP_FIXED
kMmapFd, kMmapFdOffset) != MAP_FAILED;
}
@@ -584,7 +554,6 @@ static void* ThreadEntry(void* 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.
- prctl(PR_SET_NAME, thread->name(), 0, 0, 0);
thread->thread_handle_data()->thread_ = pthread_self();
ASSERT(thread->IsValid());
thread->Run();
@@ -643,11 +612,13 @@ void Thread::YieldCPU() {
}
-class LinuxMutex : public Mutex {
+class CygwinMutex : public Mutex {
public:
- LinuxMutex() {
+ CygwinMutex() {
pthread_mutexattr_t attrs;
+ memset(&attrs, 0, sizeof(attrs));
+
int result = pthread_mutexattr_init(&attrs);
ASSERT(result == 0);
result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
@@ -656,7 +627,7 @@ class LinuxMutex : public Mutex {
ASSERT(result == 0);
}
- virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); }
+ virtual ~CygwinMutex() { pthread_mutex_destroy(&mutex_); }
virtual int Lock() {
int result = pthread_mutex_lock(&mutex_);
@@ -684,14 +655,14 @@ class LinuxMutex : public Mutex {
Mutex* OS::CreateMutex() {
- return new LinuxMutex();
+ return new CygwinMutex();
}
-class LinuxSemaphore : public Semaphore {
+class CygwinSemaphore : public Semaphore {
public:
- explicit LinuxSemaphore(int count) { sem_init(&sem_, 0, count); }
- virtual ~LinuxSemaphore() { sem_destroy(&sem_); }
+ explicit CygwinSemaphore(int count) { sem_init(&sem_, 0, count); }
+ virtual ~CygwinSemaphore() { sem_destroy(&sem_); }
virtual void Wait();
virtual bool Wait(int timeout);
@@ -701,7 +672,7 @@ class LinuxSemaphore : public Semaphore {
};
-void LinuxSemaphore::Wait() {
+void CygwinSemaphore::Wait() {
while (true) {
int result = sem_wait(&sem_);
if (result == 0) return; // Successfully got semaphore.
@@ -718,7 +689,7 @@ void LinuxSemaphore::Wait() {
#endif
-bool LinuxSemaphore::Wait(int timeout) {
+bool CygwinSemaphore::Wait(int timeout) {
const long kOneSecondMicros = 1000000; // NOLINT
// Split timeout into second and nanosecond parts.
@@ -754,163 +725,31 @@ bool LinuxSemaphore::Wait(int timeout) {
Semaphore* OS::CreateSemaphore(int count) {
- return new LinuxSemaphore(count);
+ return new CygwinSemaphore(count);
}
#ifdef ENABLE_LOGGING_AND_PROFILING
-static Sampler* active_sampler_ = NULL;
-static int vm_tid_ = 0;
-
-
-#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
-// Android runs a fairly new Linux kernel, so signal info is there,
-// but the C library doesn't have the structs defined.
-
-struct sigcontext {
- uint32_t trap_no;
- uint32_t error_code;
- uint32_t oldmask;
- uint32_t gregs[16];
- uint32_t arm_cpsr;
- uint32_t fault_address;
-};
-typedef uint32_t __sigset_t;
-typedef struct sigcontext mcontext_t;
-typedef struct ucontext {
- uint32_t uc_flags;
- struct ucontext* uc_link;
- stack_t uc_stack;
- mcontext_t uc_mcontext;
- __sigset_t uc_sigmask;
-} ucontext_t;
-enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
-
-#endif
-
-
-static int GetThreadID() {
- // Glibc doesn't provide a wrapper for gettid(2).
- return syscall(SYS_gettid);
-}
-
-
-static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
-#ifndef V8_HOST_ARCH_MIPS
- USE(info);
- if (signal != SIGPROF) return;
- if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
- if (vm_tid_ != GetThreadID()) return;
-
- TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent();
- if (sample == NULL) sample = &sample_obj;
-
- // Extracting the sample from the context is extremely machine dependent.
- ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
- mcontext_t& mcontext = ucontext->uc_mcontext;
- sample->state = Top::current_vm_state();
-#if V8_HOST_ARCH_IA32
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
-#elif V8_HOST_ARCH_X64
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
-#elif V8_HOST_ARCH_ARM
-// An undefined macro evaluates to 0, so this applies to Android's Bionic also.
-#if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
- sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
- sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
- sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
-#else
- sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
- sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
- sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
-#endif
-#elif V8_HOST_ARCH_MIPS
- // Implement this on MIPS.
- UNIMPLEMENTED();
-#endif
- active_sampler_->SampleStack(sample);
- active_sampler_->Tick(sample);
-#endif
-}
-
-
class Sampler::PlatformData : public Malloced {
public:
- enum SleepInterval {
- FULL_INTERVAL,
- HALF_INTERVAL
- };
-
explicit PlatformData(Sampler* sampler)
: sampler_(sampler),
- signal_handler_installed_(false),
- vm_tgid_(getpid()),
- signal_sender_launched_(false) {
+ signal_handler_installed_(false) {
}
void SignalSender() {
- while (sampler_->IsActive()) {
- if (rate_limiter_.SuspendIfNecessary()) continue;
- if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
- SendProfilingSignal();
- Sleep(HALF_INTERVAL);
- RuntimeProfiler::NotifyTick();
- Sleep(HALF_INTERVAL);
- } else {
- if (sampler_->IsProfiling()) SendProfilingSignal();
- if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
- Sleep(FULL_INTERVAL);
- }
- }
}
void SendProfilingSignal() {
- // Glibc doesn't provide a wrapper for tgkill(2).
- syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
- }
-
- void Sleep(SleepInterval full_or_half) {
- // Convert ms to us and subtract 100 us to compensate delays
- // occuring during signal delivery.
- useconds_t interval = sampler_->interval_ * 1000 - 100;
- if (full_or_half == HALF_INTERVAL) interval /= 2;
- int result = usleep(interval);
-#ifdef DEBUG
- if (result != 0 && errno != EINTR) {
- fprintf(stderr,
- "SignalSender usleep error; interval = %u, errno = %d\n",
- interval,
- errno);
- ASSERT(result == 0 || errno == EINTR);
- }
-#endif
- USE(result);
}
Sampler* sampler_;
bool signal_handler_installed_;
struct sigaction old_signal_handler_;
- int vm_tgid_;
- bool signal_sender_launched_;
- pthread_t signal_sender_thread_;
- RuntimeProfilerRateLimiter rate_limiter_;
};
-static void* SenderEntry(void* arg) {
- Sampler::PlatformData* data =
- reinterpret_cast<Sampler::PlatformData*>(arg);
- data->SignalSender();
- return 0;
-}
-
-
Sampler::Sampler(int interval)
: interval_(interval),
profiling_(false),
@@ -927,55 +766,14 @@ Sampler::~Sampler() {
void Sampler::Start() {
- // There can only be one active sampler at the time on POSIX
- // platforms.
- ASSERT(!IsActive());
- vm_tid_ = GetThreadID();
-
- // Request profiling signals.
- struct sigaction sa;
- sa.sa_sigaction = ProfilerSignalHandler;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_RESTART | SA_SIGINFO;
- if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
- data_->signal_handler_installed_ = true;
-
- // Start a thread that sends SIGPROF signal to VM thread.
- // Sending the signal ourselves instead of relying on itimer provides
- // much better accuracy.
- SetActive(true);
- if (pthread_create(
- &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
- data_->signal_sender_launched_ = true;
- }
-
- // Set this sampler as the active sampler.
- active_sampler_ = this;
+ active_ = true;
}
void Sampler::Stop() {
- SetActive(false);
-
- // Wait for signal sender termination (it will exit after setting
- // active_ to false).
- if (data_->signal_sender_launched_) {
- Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
- pthread_join(data_->signal_sender_thread_, NULL);
- data_->signal_sender_launched_ = false;
- }
-
- // Restore old signal handler
- if (data_->signal_handler_installed_) {
- 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
+} } // namespace v8::internal
\ No newline at end of file
diff --git a/src/platform.h b/src/platform.h
index 0d7d2e9..8cb1561 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -383,10 +383,14 @@ class Thread: public ThreadHandle {
// LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
// to ensure that enumeration type has correct value range (see Issue 830 for
// more details).
+#ifdef __CYGWIN__
+ typedef void* LocalStorageKey;
+#else
enum LocalStorageKey {
LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
};
+#endif
// Create new thread.
Thread();
diff --git a/tools/utils.py b/tools/utils.py
index 8083091..fb94d14 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -49,6 +49,8 @@ def GuessOS():
return 'linux'
elif id == 'Darwin':
return 'macos'
+ elif id.find('CYGWIN') >= 0:
+ return 'cygwin'
elif id == 'Windows' or id == 'Microsoft':
# On Windows Vista platform.system() can return 'Microsoft' with some
# versions of Python, see http://bugs.python.org/issue1082
--
1.7.3.1.msysgit.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment