Skip to content
This repository
Browse code

V8 cygwin support

  • Loading branch information...
commit fd013d17a21bbf7675d3bef59b2a76a58cb311f5 1 parent 67e352e
Bert Belder piscisaureus authored ry committed
5 deps/v8/SConstruct
@@ -188,6 +188,9 @@ LIBRARY_FLAGS = {
188 188 'LIBPATH' : ['/usr/local/lib'],
189 189 'CCFLAGS': ['-ansi'],
190 190 },
  191 + 'os:cygwin': {
  192 + 'WARNINGFLAGS': ['-Werror'],
  193 + },
191 194 'os:win32': {
192 195 'CCFLAGS': ['-DWIN32'],
193 196 'CXXFLAGS': ['-DWIN32'],
@@ -691,7 +694,7 @@ SIMPLE_OPTIONS = {
691 694 'help': 'the toolchain to use (%s)' % TOOLCHAIN_GUESS
692 695 },
693 696 'os': {
694   - 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris'],
  697 + 'values': ['freebsd', 'linux', 'macos', 'win32', 'android', 'openbsd', 'solaris', 'cygwin'],
695 698 'default': OS_GUESS,
696 699 'help': 'the os to build for (%s)' % OS_GUESS
697 700 },
1  deps/v8/src/SConscript
@@ -234,6 +234,7 @@ SOURCES = {
234 234 'os:android': ['platform-linux.cc', 'platform-posix.cc'],
235 235 'os:macos': ['platform-macos.cc', 'platform-posix.cc'],
236 236 'os:solaris': ['platform-solaris.cc', 'platform-posix.cc'],
  237 + 'os:cygwin': ['platform-cygwin.cc', 'platform-posix.cc'],
237 238 'os:nullos': ['platform-nullos.cc'],
238 239 'os:win32': ['platform-win32.cc'],
239 240 'mode:release': [],
779 deps/v8/src/platform-cygwin.cc
... ... @@ -0,0 +1,779 @@
  1 +// Copyright 2006-2008 the V8 project authors. All rights reserved.
  2 +// Redistribution and use in source and binary forms, with or without
  3 +// modification, are permitted provided that the following conditions are
  4 +// met:
  5 +//
  6 +// * Redistributions of source code must retain the above copyright
  7 +// notice, this list of conditions and the following disclaimer.
  8 +// * Redistributions in binary form must reproduce the above
  9 +// copyright notice, this list of conditions and the following
  10 +// disclaimer in the documentation and/or other materials provided
  11 +// with the distribution.
  12 +// * Neither the name of Google Inc. nor the names of its
  13 +// contributors may be used to endorse or promote products derived
  14 +// from this software without specific prior written permission.
  15 +//
  16 +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17 +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18 +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19 +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20 +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21 +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22 +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23 +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24 +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25 +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26 +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27 +
  28 +// Platform specific code for Cygwin goes here. For the POSIX comaptible parts
  29 +// the implementation is in platform-posix.cc.
  30 +
  31 +#include <pthread.h>
  32 +#include <semaphore.h>
  33 +#include <signal.h>
  34 +#include <sys/time.h>
  35 +#include <sys/resource.h>
  36 +#include <sys/types.h>
  37 +#include <stdlib.h>
  38 +
  39 +// Ubuntu Dapper requires memory pages to be marked as
  40 +// executable. Otherwise, OS raises an exception when executing code
  41 +// in that page.
  42 +#include <sys/types.h> // mmap & munmap
  43 +#include <sys/mman.h> // mmap & munmap
  44 +#include <sys/stat.h> // open
  45 +#include <fcntl.h> // open
  46 +#include <unistd.h> // sysconf
  47 +#ifdef __GLIBC__
  48 +#include <execinfo.h> // backtrace, backtrace_symbols
  49 +#endif // def __GLIBC__
  50 +#include <strings.h> // index
  51 +#include <errno.h>
  52 +#include <stdarg.h>
  53 +
  54 +#undef MAP_TYPE
  55 +
  56 +#include "v8.h"
  57 +
  58 +#include "platform.h"
  59 +#include "top.h"
  60 +#include "v8threads.h"
  61 +#include "vm-state-inl.h"
  62 +
  63 +
  64 +namespace v8 {
  65 +namespace internal {
  66 +
  67 +// 0 is never a valid thread id on Linux since tids and pids share a
  68 +// name space and pid 0 is reserved (see man 2 kill).
  69 +static const pthread_t kNoThread = (pthread_t) 0;
  70 +
  71 +
  72 +double ceiling(double x) {
  73 + return ceil(x);
  74 +}
  75 +
  76 +
  77 +void OS::Setup() {
  78 + // Seed the random number generator.
  79 + // Convert the current time to a 64-bit integer first, before converting it
  80 + // to an unsigned. Going directly can cause an overflow and the seed to be
  81 + // set to all ones. The seed will be identical for different instances that
  82 + // call this setup code within the same millisecond.
  83 + uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
  84 + srandom(static_cast<unsigned int>(seed));
  85 +}
  86 +
  87 +
  88 +uint64_t OS::CpuFeaturesImpliedByPlatform() {
  89 +#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
  90 + // Here gcc is telling us that we are on an ARM and gcc is assuming that we
  91 + // have VFP3 instructions. If gcc can assume it then so can we.
  92 + return 1u << VFP3;
  93 +#elif CAN_USE_ARMV7_INSTRUCTIONS
  94 + return 1u << ARMv7;
  95 +#else
  96 + return 0; // Linux runs on anything.
  97 +#endif
  98 +}
  99 +
  100 +
  101 +#ifdef __arm__
  102 +static bool CPUInfoContainsString(const char * search_string) {
  103 + const char* file_name = "/proc/cpuinfo";
  104 + // This is written as a straight shot one pass parser
  105 + // and not using STL string and ifstream because,
  106 + // on Linux, it's reading from a (non-mmap-able)
  107 + // character special device.
  108 + FILE* f = NULL;
  109 + const char* what = search_string;
  110 +
  111 + if (NULL == (f = fopen(file_name, "r")))
  112 + return false;
  113 +
  114 + int k;
  115 + while (EOF != (k = fgetc(f))) {
  116 + if (k == *what) {
  117 + ++what;
  118 + while ((*what != '\0') && (*what == fgetc(f))) {
  119 + ++what;
  120 + }
  121 + if (*what == '\0') {
  122 + fclose(f);
  123 + return true;
  124 + } else {
  125 + what = search_string;
  126 + }
  127 + }
  128 + }
  129 + fclose(f);
  130 +
  131 + // Did not find string in the proc file.
  132 + return false;
  133 +}
  134 +
  135 +bool OS::ArmCpuHasFeature(CpuFeature feature) {
  136 + const char* search_string = NULL;
  137 + // Simple detection of VFP at runtime for Linux.
  138 + // It is based on /proc/cpuinfo, which reveals hardware configuration
  139 + // to user-space applications. According to ARM (mid 2009), no similar
  140 + // facility is universally available on the ARM architectures,
  141 + // so it's up to individual OSes to provide such.
  142 + switch (feature) {
  143 + case VFP3:
  144 + search_string = "vfpv3";
  145 + break;
  146 + case ARMv7:
  147 + search_string = "ARMv7";
  148 + break;
  149 + default:
  150 + UNREACHABLE();
  151 + }
  152 +
  153 + if (CPUInfoContainsString(search_string)) {
  154 + return true;
  155 + }
  156 +
  157 + if (feature == VFP3) {
  158 + // Some old kernels will report vfp not vfpv3. Here we make a last attempt
  159 + // to detect vfpv3 by checking for vfp *and* neon, since neon is only
  160 + // available on architectures with vfpv3.
  161 + // Checking neon on its own is not enough as it is possible to have neon
  162 + // without vfp.
  163 + if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) {
  164 + return true;
  165 + }
  166 + }
  167 +
  168 + return false;
  169 +}
  170 +#endif // def __arm__
  171 +
  172 +
  173 +int OS::ActivationFrameAlignment() {
  174 +#ifdef V8_TARGET_ARCH_ARM
  175 + // On EABI ARM targets this is required for fp correctness in the
  176 + // runtime system.
  177 + return 8;
  178 +#elif V8_TARGET_ARCH_MIPS
  179 + return 8;
  180 +#endif
  181 + // With gcc 4.4 the tree vectorization optimizer can generate code
  182 + // that requires 16 byte alignment such as movdqa on x86.
  183 + return 16;
  184 +}
  185 +
  186 +
  187 +void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
  188 + __asm__ __volatile__("" : : : "memory");
  189 + // An x86 store acts as a release barrier.
  190 + *ptr = value;
  191 +}
  192 +
  193 +const char* OS::LocalTimezone(double time) {
  194 + if (isnan(time)) return "";
  195 + time_t tv = static_cast<time_t>(floor(time/msPerSecond));
  196 + struct tm* t = localtime(&tv);
  197 + if (NULL == t) return "";
  198 + return tzname[0]; // The location of the timezone string on Cywin.
  199 +}
  200 +
  201 +
  202 +double OS::LocalTimeOffset() {
  203 + // On Cygwin, struct tm does not contain a tm_gmtoff field.
  204 + time_t utc = time(NULL);
  205 + ASSERT(utc != -1);
  206 + struct tm* loc = localtime(&utc);
  207 + ASSERT(loc != NULL);
  208 + return static_cast<double>((mktime(loc) - utc) * msPerSecond);
  209 +}
  210 +
  211 +
  212 +// We keep the lowest and highest addresses mapped as a quick way of
  213 +// determining that pointers are outside the heap (used mostly in assertions
  214 +// and verification). The estimate is conservative, ie, not all addresses in
  215 +// 'allocated' space are actually allocated to our heap. The range is
  216 +// [lowest, highest), inclusive on the low and and exclusive on the high end.
  217 +static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
  218 +static void* highest_ever_allocated = reinterpret_cast<void*>(0);
  219 +
  220 +
  221 +static void UpdateAllocatedSpaceLimits(void* address, int size) {
  222 + lowest_ever_allocated = Min(lowest_ever_allocated, address);
  223 + highest_ever_allocated =
  224 + Max(highest_ever_allocated,
  225 + reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
  226 +}
  227 +
  228 +
  229 +bool OS::IsOutsideAllocatedSpace(void* address) {
  230 + return address < lowest_ever_allocated || address >= highest_ever_allocated;
  231 +}
  232 +
  233 +
  234 +size_t OS::AllocateAlignment() {
  235 + return sysconf(_SC_PAGESIZE);
  236 +}
  237 +
  238 +
  239 +void* OS::Allocate(const size_t requested,
  240 + size_t* allocated,
  241 + bool is_executable) {
  242 + const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
  243 + int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
  244 + void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  245 + if (mbase == MAP_FAILED) {
  246 + LOG(StringEvent("OS::Allocate", "mmap failed"));
  247 + return NULL;
  248 + }
  249 + *allocated = msize;
  250 + UpdateAllocatedSpaceLimits(mbase, msize);
  251 + return mbase;
  252 +}
  253 +
  254 +
  255 +void OS::Free(void* address, const size_t size) {
  256 + // TODO(1240712): munmap has a return value which is ignored here.
  257 + int result = munmap(address, size);
  258 + USE(result);
  259 + ASSERT(result == 0);
  260 +}
  261 +
  262 +
  263 +#ifdef ENABLE_HEAP_PROTECTION
  264 +
  265 +void OS::Protect(void* address, size_t size) {
  266 + // TODO(1240712): mprotect has a return value which is ignored here.
  267 + mprotect(address, size, PROT_READ);
  268 +}
  269 +
  270 +
  271 +void OS::Unprotect(void* address, size_t size, bool is_executable) {
  272 + // TODO(1240712): mprotect has a return value which is ignored here.
  273 + int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
  274 + mprotect(address, size, prot);
  275 +}
  276 +
  277 +#endif
  278 +
  279 +
  280 +void OS::Sleep(int milliseconds) {
  281 + unsigned int ms = static_cast<unsigned int>(milliseconds);
  282 + usleep(1000 * ms);
  283 +}
  284 +
  285 +
  286 +void OS::Abort() {
  287 + // Redirect to std abort to signal abnormal program termination.
  288 + abort();
  289 +}
  290 +
  291 +
  292 +void OS::DebugBreak() {
  293 +// TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x,
  294 +// which is the architecture of generated code).
  295 +#if (defined(__arm__) || defined(__thumb__)) && \
  296 + defined(CAN_USE_ARMV5_INSTRUCTIONS)
  297 + asm("bkpt 0");
  298 +#elif defined(__mips__)
  299 + asm("break");
  300 +#else
  301 + asm("int $3");
  302 +#endif
  303 +}
  304 +
  305 +
  306 +class PosixMemoryMappedFile : public OS::MemoryMappedFile {
  307 + public:
  308 + PosixMemoryMappedFile(FILE* file, void* memory, int size)
  309 + : file_(file), memory_(memory), size_(size) { }
  310 + virtual ~PosixMemoryMappedFile();
  311 + virtual void* memory() { return memory_; }
  312 + virtual int size() { return size_; }
  313 + private:
  314 + FILE* file_;
  315 + void* memory_;
  316 + int size_;
  317 +};
  318 +
  319 +
  320 +OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
  321 + FILE* file = fopen(name, "w+");
  322 + if (file == NULL) return NULL;
  323 +
  324 + fseek(file, 0, SEEK_END);
  325 + int size = ftell(file);
  326 +
  327 + void* memory =
  328 + mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
  329 + return new PosixMemoryMappedFile(file, memory, size);
  330 +}
  331 +
  332 +
  333 +OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
  334 + void* initial) {
  335 + FILE* file = fopen(name, "w+");
  336 + if (file == NULL) return NULL;
  337 + int result = fwrite(initial, size, 1, file);
  338 + if (result < 1) {
  339 + fclose(file);
  340 + return NULL;
  341 + }
  342 + void* memory =
  343 + mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
  344 + return new PosixMemoryMappedFile(file, memory, size);
  345 +}
  346 +
  347 +
  348 +PosixMemoryMappedFile::~PosixMemoryMappedFile() {
  349 + if (memory_) munmap(memory_, size_);
  350 + fclose(file_);
  351 +}
  352 +
  353 +
  354 +void OS::LogSharedLibraryAddresses() {
  355 +#ifdef ENABLE_LOGGING_AND_PROFILING
  356 + // This function assumes that the layout of the file is as follows:
  357 + // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
  358 + // If we encounter an unexpected situation we abort scanning further entries.
  359 + FILE* fp = fopen("/proc/self/maps", "r");
  360 + if (fp == NULL) return;
  361 +
  362 + // Allocate enough room to be able to store a full file name.
  363 + const int kLibNameLen = FILENAME_MAX + 1;
  364 + char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
  365 +
  366 + // This loop will terminate once the scanning hits an EOF.
  367 + while (true) {
  368 + uintptr_t start, end;
  369 + char attr_r, attr_w, attr_x, attr_p;
  370 + // Parse the addresses and permission bits at the beginning of the line.
  371 + if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
  372 + if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
  373 +
  374 + int c;
  375 + if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
  376 + // Found a read-only executable entry. Skip characters until we reach
  377 + // the beginning of the filename or the end of the line.
  378 + do {
  379 + c = getc(fp);
  380 + } while ((c != EOF) && (c != '\n') && (c != '/'));
  381 + if (c == EOF) break; // EOF: Was unexpected, just exit.
  382 +
  383 + // Process the filename if found.
  384 + if (c == '/') {
  385 + ungetc(c, fp); // Push the '/' back into the stream to be read below.
  386 +
  387 + // Read to the end of the line. Exit if the read fails.
  388 + if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
  389 +
  390 + // Drop the newline character read by fgets. We do not need to check
  391 + // for a zero-length string because we know that we at least read the
  392 + // '/' character.
  393 + lib_name[strlen(lib_name) - 1] = '\0';
  394 + } else {
  395 + // No library name found, just record the raw address range.
  396 + snprintf(lib_name, kLibNameLen,
  397 + "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
  398 + }
  399 + LOG(SharedLibraryEvent(lib_name, start, end));
  400 + } else {
  401 + // Entry not describing executable data. Skip to end of line to setup
  402 + // reading the next entry.
  403 + do {
  404 + c = getc(fp);
  405 + } while ((c != EOF) && (c != '\n'));
  406 + if (c == EOF) break;
  407 + }
  408 + }
  409 + free(lib_name);
  410 + fclose(fp);
  411 +#endif
  412 +}
  413 +
  414 +
  415 +void OS::SignalCodeMovingGC() {
  416 +}
  417 +
  418 +
  419 +int OS::StackWalk(Vector<OS::StackFrame> frames) {
  420 + // backtrace is a glibc extension.
  421 +#ifdef __GLIBC__
  422 + int frames_size = frames.length();
  423 + ScopedVector<void*> addresses(frames_size);
  424 +
  425 + int frames_count = backtrace(addresses.start(), frames_size);
  426 +
  427 + char** symbols = backtrace_symbols(addresses.start(), frames_count);
  428 + if (symbols == NULL) {
  429 + return kStackWalkError;
  430 + }
  431 +
  432 + for (int i = 0; i < frames_count; i++) {
  433 + frames[i].address = addresses[i];
  434 + // Format a text representation of the frame based on the information
  435 + // available.
  436 + SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
  437 + "%s",
  438 + symbols[i]);
  439 + // Make sure line termination is in place.
  440 + frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
  441 + }
  442 +
  443 + free(symbols);
  444 +
  445 + return frames_count;
  446 +#else // ndef __GLIBC__
  447 + return 0;
  448 +#endif // ndef __GLIBC__
  449 +}
  450 +
  451 +
  452 +// Constants used for mmap.
  453 +static const int kMmapFd = -1;
  454 +static const int kMmapFdOffset = 0;
  455 +
  456 +
  457 +VirtualMemory::VirtualMemory(size_t size) {
  458 + address_ = mmap(NULL, size, PROT_NONE,
  459 + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
  460 + kMmapFd, kMmapFdOffset);
  461 + size_ = size;
  462 +}
  463 +
  464 +
  465 +VirtualMemory::~VirtualMemory() {
  466 + if (IsReserved()) {
  467 + if (0 == munmap(address(), size())) address_ = MAP_FAILED;
  468 + }
  469 +}
  470 +
  471 +
  472 +bool VirtualMemory::IsReserved() {
  473 + return address_ != MAP_FAILED;
  474 +}
  475 +
  476 +
  477 +bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
  478 + int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
  479 +
  480 + if (mprotect(address, size, prot) != 0) {
  481 + return false;
  482 + }
  483 +
  484 + UpdateAllocatedSpaceLimits(address, size);
  485 + return true;
  486 +}
  487 +
  488 +
  489 +bool VirtualMemory::Uncommit(void* address, size_t size) {
  490 + return mmap(address, size, PROT_NONE,
  491 + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, // | MAP_FIXED, - Cygwin doesn't have MAP_FIXED
  492 + kMmapFd, kMmapFdOffset) != MAP_FAILED;
  493 +}
  494 +
  495 +
  496 +class ThreadHandle::PlatformData : public Malloced {
  497 + public:
  498 + explicit PlatformData(ThreadHandle::Kind kind) {
  499 + Initialize(kind);
  500 + }
  501 +
  502 + void Initialize(ThreadHandle::Kind kind) {
  503 + switch (kind) {
  504 + case ThreadHandle::SELF: thread_ = pthread_self(); break;
  505 + case ThreadHandle::INVALID: thread_ = kNoThread; break;
  506 + }
  507 + }
  508 +
  509 + pthread_t thread_; // Thread handle for pthread.
  510 +};
  511 +
  512 +
  513 +ThreadHandle::ThreadHandle(Kind kind) {
  514 + data_ = new PlatformData(kind);
  515 +}
  516 +
  517 +
  518 +void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
  519 + data_->Initialize(kind);
  520 +}
  521 +
  522 +
  523 +ThreadHandle::~ThreadHandle() {
  524 + delete data_;
  525 +}
  526 +
  527 +
  528 +bool ThreadHandle::IsSelf() const {
  529 + return pthread_equal(data_->thread_, pthread_self());
  530 +}
  531 +
  532 +
  533 +bool ThreadHandle::IsValid() const {
  534 + return data_->thread_ != kNoThread;
  535 +}
  536 +
  537 +
  538 +Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
  539 + set_name("v8:<unknown>");
  540 +}
  541 +
  542 +
  543 +Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
  544 + set_name(name);
  545 +}
  546 +
  547 +
  548 +Thread::~Thread() {
  549 +}
  550 +
  551 +
  552 +static void* ThreadEntry(void* arg) {
  553 + Thread* thread = reinterpret_cast<Thread*>(arg);
  554 + // This is also initialized by the first argument to pthread_create() but we
  555 + // don't know which thread will run first (the original thread or the new
  556 + // one) so we initialize it here too.
  557 + thread->thread_handle_data()->thread_ = pthread_self();
  558 + ASSERT(thread->IsValid());
  559 + thread->Run();
  560 + return NULL;
  561 +}
  562 +
  563 +
  564 +void Thread::set_name(const char* name) {
  565 + strncpy(name_, name, sizeof(name_));
  566 + name_[sizeof(name_) - 1] = '\0';
  567 +}
  568 +
  569 +
  570 +void Thread::Start() {
  571 + pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
  572 + ASSERT(IsValid());
  573 +}
  574 +
  575 +
  576 +void Thread::Join() {
  577 + pthread_join(thread_handle_data()->thread_, NULL);
  578 +}
  579 +
  580 +
  581 +Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
  582 + pthread_key_t key;
  583 + int result = pthread_key_create(&key, NULL);
  584 + USE(result);
  585 + ASSERT(result == 0);
  586 + return static_cast<LocalStorageKey>(key);
  587 +}
  588 +
  589 +
  590 +void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
  591 + pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
  592 + int result = pthread_key_delete(pthread_key);
  593 + USE(result);
  594 + ASSERT(result == 0);
  595 +}
  596 +
  597 +
  598 +void* Thread::GetThreadLocal(LocalStorageKey key) {
  599 + pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
  600 + return pthread_getspecific(pthread_key);
  601 +}
  602 +
  603 +
  604 +void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
  605 + pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
  606 + pthread_setspecific(pthread_key, value);
  607 +}
  608 +
  609 +
  610 +void Thread::YieldCPU() {
  611 + sched_yield();
  612 +}
  613 +
  614 +
  615 +class CygwinMutex : public Mutex {
  616 + public:
  617 +
  618 + CygwinMutex() {
  619 + pthread_mutexattr_t attrs;
  620 + memset(&attrs, 0, sizeof(attrs));
  621 +
  622 + int result = pthread_mutexattr_init(&attrs);
  623 + ASSERT(result == 0);
  624 + result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
  625 + ASSERT(result == 0);
  626 + result = pthread_mutex_init(&mutex_, &attrs);
  627 + ASSERT(result == 0);
  628 + }
  629 +
  630 + virtual ~CygwinMutex() { pthread_mutex_destroy(&mutex_); }
  631 +
  632 + virtual int Lock() {
  633 + int result = pthread_mutex_lock(&mutex_);
  634 + return result;
  635 + }
  636 +
  637 + virtual int Unlock() {
  638 + int result = pthread_mutex_unlock(&mutex_);
  639 + return result;
  640 + }
  641 +
  642 + virtual bool TryLock() {
  643 + int result = pthread_mutex_trylock(&mutex_);
  644 + // Return false if the lock is busy and locking failed.
  645 + if (result == EBUSY) {
  646 + return false;
  647 + }
  648 + ASSERT(result == 0); // Verify no other errors.
  649 + return true;
  650 + }
  651 +
  652 + private:
  653 + pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
  654 +};
  655 +
  656 +
  657 +Mutex* OS::CreateMutex() {
  658 + return new CygwinMutex();
  659 +}
  660 +
  661 +
  662 +class CygwinSemaphore : public Semaphore {
  663 + public:
  664 + explicit CygwinSemaphore(int count) { sem_init(&sem_, 0, count); }
  665 + virtual ~CygwinSemaphore() { sem_destroy(&sem_); }
  666 +
  667 + virtual void Wait();
  668 + virtual bool Wait(int timeout);
  669 + virtual void Signal() { sem_post(&sem_); }
  670 + private:
  671 + sem_t sem_;
  672 +};
  673 +
  674 +
  675 +void CygwinSemaphore::Wait() {
  676 + while (true) {
  677 + int result = sem_wait(&sem_);
  678 + if (result == 0) return; // Successfully got semaphore.
  679 + CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
  680 + }
  681 +}
  682 +
  683 +
  684 +#ifndef TIMEVAL_TO_TIMESPEC
  685 +#define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
  686 + (ts)->tv_sec = (tv)->tv_sec; \
  687 + (ts)->tv_nsec = (tv)->tv_usec * 1000; \
  688 +} while (false)
  689 +#endif
  690 +
  691 +
  692 +bool CygwinSemaphore::Wait(int timeout) {
  693 + const long kOneSecondMicros = 1000000; // NOLINT
  694 +
  695 + // Split timeout into second and nanosecond parts.
  696 + struct timeval delta;
  697 + delta.tv_usec = timeout % kOneSecondMicros;
  698 + delta.tv_sec = timeout / kOneSecondMicros;
  699 +
  700 + struct timeval current_time;
  701 + // Get the current time.
  702 + if (gettimeofday(&current_time, NULL) == -1) {
  703 + return false;
  704 + }
  705 +
  706 + // Calculate time for end of timeout.
  707 + struct timeval end_time;
  708 + timeradd(&current_time, &delta, &end_time);
  709 +
  710 + struct timespec ts;
  711 + TIMEVAL_TO_TIMESPEC(&end_time, &ts);
  712 + // Wait for semaphore signalled or timeout.
  713 + while (true) {
  714 + int result = sem_timedwait(&sem_, &ts);
  715 + if (result == 0) return true; // Successfully got semaphore.
  716 + if (result > 0) {
  717 + // For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1.
  718 + errno = result;
  719 + result = -1;
  720 + }
  721 + if (result == -1 && errno == ETIMEDOUT) return false; // Timeout.
  722 + CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
  723 + }
  724 +}
  725 +
  726 +
  727 +Semaphore* OS::CreateSemaphore(int count) {
  728 + return new CygwinSemaphore(count);
  729 +}
  730 +
  731 +
  732 +#ifdef ENABLE_LOGGING_AND_PROFILING
  733 +
  734 +class Sampler::PlatformData : public Malloced {
  735 + public:
  736 + explicit PlatformData(Sampler* sampler)
  737 + : sampler_(sampler),
  738 + signal_handler_installed_(false) {
  739 + }
  740 +
  741 + void SignalSender() {
  742 + }
  743 +
  744 + void SendProfilingSignal() {
  745 + }
  746 +
  747 + Sampler* sampler_;
  748 + bool signal_handler_installed_;
  749 + struct sigaction old_signal_handler_;
  750 +};
  751 +
  752 +
  753 +Sampler::Sampler(int interval)
  754 + : interval_(interval),
  755 + profiling_(false),
  756 + active_(false),
  757 + samples_taken_(0) {
  758 + data_ = new PlatformData(this);
  759 +}
  760 +
  761 +
  762 +Sampler::~Sampler() {
  763 + ASSERT(!data_->signal_sender_launched_);
  764 + delete data_;
  765 +}
  766 +
  767 +
  768 +void Sampler::Start() {
  769 + active_ = true;
  770 +}
  771 +
  772 +
  773 +void Sampler::Stop() {
  774 + active_ = false;
  775 +}
  776 +
  777 +#endif // ENABLE_LOGGING_AND_PROFILING
  778 +
  779 +} } // namespace v8::internal
4 deps/v8/src/platform.h
@@ -383,10 +383,14 @@ class Thread: public ThreadHandle {
383 383 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
384 384 // to ensure that enumeration type has correct value range (see Issue 830 for
385 385 // more details).
  386 +#ifdef __CYGWIN__
  387 + typedef void* LocalStorageKey;
  388 +#else
386 389 enum LocalStorageKey {
387 390 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
388 391 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
389 392 };
  393 +#endif
390 394
391 395 // Create new thread.
392 396 Thread();
2  deps/v8/tools/utils.py
@@ -49,6 +49,8 @@ def GuessOS():
49 49 return 'linux'
50 50 elif id == 'Darwin':
51 51 return 'macos'
  52 + elif id.find('CYGWIN') >= 0:
  53 + return 'cygwin'
52 54 elif id == 'Windows' or id == 'Microsoft':
53 55 # On Windows Vista platform.system() can return 'Microsoft' with some
54 56 # versions of Python, see http://bugs.python.org/issue1082

0 comments on commit fd013d1

Please sign in to comment.
Something went wrong with that request. Please try again.