Created
February 10, 2011 03:06
-
-
Save piscisaureus/819841 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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