Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 POSIX goes here. This is not a platform on its
     29 // own but contains the parts which are the same across POSIX platforms Linux,
     30 // Mac OS, FreeBSD and OpenBSD.
     31 
     32 #include "platform-posix.h"
     33 
     34 #include <dlfcn.h>
     35 #include <pthread.h>
     36 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
     37 #include <pthread_np.h>  // for pthread_set_name_np
     38 #endif
     39 #include <sched.h>  // for sched_yield
     40 #include <unistd.h>
     41 #include <errno.h>
     42 #include <time.h>
     43 
     44 #include <sys/mman.h>
     45 #include <sys/socket.h>
     46 #include <sys/resource.h>
     47 #include <sys/time.h>
     48 #include <sys/types.h>
     49 #include <sys/stat.h>
     50 #if defined(__linux__)
     51 #include <sys/prctl.h>  // for prctl
     52 #endif
     53 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
     54     defined(__NetBSD__) || defined(__OpenBSD__)
     55 #include <sys/sysctl.h>  // for sysctl
     56 #endif
     57 
     58 #include <arpa/inet.h>
     59 #include <netinet/in.h>
     60 #include <netdb.h>
     61 
     62 #undef MAP_TYPE
     63 
     64 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
     65 #define LOG_TAG "v8"
     66 #include <android/log.h>
     67 #endif
     68 
     69 #include "v8.h"
     70 
     71 #include "codegen.h"
     72 #include "platform.h"
     73 
     74 namespace v8 {
     75 namespace internal {
     76 
     77 // 0 is never a valid thread id.
     78 static const pthread_t kNoThread = (pthread_t) 0;
     79 
     80 
     81 uint64_t OS::CpuFeaturesImpliedByPlatform() {
     82 #if defined(__APPLE__)
     83   // Mac OS X requires all these to install so we can assume they are present.
     84   // These constants are defined by the CPUid instructions.
     85   const uint64_t one = 1;
     86   return (one << SSE2) | (one << CMOV) | (one << RDTSC) | (one << CPUID);
     87 #else
     88   return 0;  // Nothing special about the other systems.
     89 #endif
     90 }
     91 
     92 
     93 // Maximum size of the virtual memory.  0 means there is no artificial
     94 // limit.
     95 
     96 intptr_t OS::MaxVirtualMemory() {
     97   struct rlimit limit;
     98   int result = getrlimit(RLIMIT_DATA, &limit);
     99   if (result != 0) return 0;
    100   return limit.rlim_cur;
    101 }
    102 
    103 
    104 int OS::ActivationFrameAlignment() {
    105 #if V8_TARGET_ARCH_ARM
    106   // On EABI ARM targets this is required for fp correctness in the
    107   // runtime system.
    108   return 8;
    109 #elif V8_TARGET_ARCH_MIPS
    110   return 8;
    111 #else
    112   // Otherwise we just assume 16 byte alignment, i.e.:
    113   // - With gcc 4.4 the tree vectorization optimizer can generate code
    114   //   that requires 16 byte alignment such as movdqa on x86.
    115   // - Mac OS X and Solaris (64-bit) activation frames must be 16 byte-aligned;
    116   //   see "Mac OS X ABI Function Call Guide"
    117   return 16;
    118 #endif
    119 }
    120 
    121 
    122 intptr_t OS::CommitPageSize() {
    123   static intptr_t page_size = getpagesize();
    124   return page_size;
    125 }
    126 
    127 
    128 void OS::Free(void* address, const size_t size) {
    129   // TODO(1240712): munmap has a return value which is ignored here.
    130   int result = munmap(address, size);
    131   USE(result);
    132   ASSERT(result == 0);
    133 }
    134 
    135 
    136 // Get rid of writable permission on code allocations.
    137 void OS::ProtectCode(void* address, const size_t size) {
    138 #if defined(__CYGWIN__)
    139   DWORD old_protect;
    140   VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
    141 #elif defined(__native_client__)
    142   // The Native Client port of V8 uses an interpreter, so
    143   // code pages don't need PROT_EXEC.
    144   mprotect(address, size, PROT_READ);
    145 #else
    146   mprotect(address, size, PROT_READ | PROT_EXEC);
    147 #endif
    148 }
    149 
    150 
    151 // Create guard pages.
    152 void OS::Guard(void* address, const size_t size) {
    153 #if defined(__CYGWIN__)
    154   DWORD oldprotect;
    155   VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect);
    156 #else
    157   mprotect(address, size, PROT_NONE);
    158 #endif
    159 }
    160 
    161 
    162 void* OS::GetRandomMmapAddr() {
    163 #if defined(__native_client__)
    164   // TODO(bradchen): restore randomization once Native Client gets
    165   // smarter about using mmap address hints.
    166   // See http://code.google.com/p/nativeclient/issues/3341
    167   return NULL;
    168 #endif
    169   Isolate* isolate = Isolate::UncheckedCurrent();
    170   // Note that the current isolate isn't set up in a call path via
    171   // CpuFeatures::Probe. We don't care about randomization in this case because
    172   // the code page is immediately freed.
    173   if (isolate != NULL) {
    174 #if V8_TARGET_ARCH_X64
    175     uint64_t rnd1 = V8::RandomPrivate(isolate);
    176     uint64_t rnd2 = V8::RandomPrivate(isolate);
    177     uint64_t raw_addr = (rnd1 << 32) ^ rnd2;
    178     // Currently available CPUs have 48 bits of virtual addressing.  Truncate
    179     // the hint address to 46 bits to give the kernel a fighting chance of
    180     // fulfilling our placement request.
    181     raw_addr &= V8_UINT64_C(0x3ffffffff000);
    182 #else
    183     uint32_t raw_addr = V8::RandomPrivate(isolate);
    184 
    185     raw_addr &= 0x3ffff000;
    186 
    187 # ifdef __sun
    188     // For our Solaris/illumos mmap hint, we pick a random address in the bottom
    189     // half of the top half of the address space (that is, the third quarter).
    190     // Because we do not MAP_FIXED, this will be treated only as a hint -- the
    191     // system will not fail to mmap() because something else happens to already
    192     // be mapped at our random address. We deliberately set the hint high enough
    193     // to get well above the system's break (that is, the heap); Solaris and
    194     // illumos will try the hint and if that fails allocate as if there were
    195     // no hint at all. The high hint prevents the break from getting hemmed in
    196     // at low values, ceding half of the address space to the system heap.
    197     raw_addr += 0x80000000;
    198 # else
    199     // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
    200     // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
    201     // 10.6 and 10.7.
    202     raw_addr += 0x20000000;
    203 # endif
    204 #endif
    205     return reinterpret_cast<void*>(raw_addr);
    206   }
    207   return NULL;
    208 }
    209 
    210 
    211 size_t OS::AllocateAlignment() {
    212   return getpagesize();
    213 }
    214 
    215 
    216 void OS::Sleep(int milliseconds) {
    217   useconds_t ms = static_cast<useconds_t>(milliseconds);
    218   usleep(1000 * ms);
    219 }
    220 
    221 
    222 int OS::NumberOfCores() {
    223   return sysconf(_SC_NPROCESSORS_ONLN);
    224 }
    225 
    226 
    227 void OS::Abort() {
    228   // Redirect to std abort to signal abnormal program termination.
    229   if (FLAG_break_on_abort) {
    230     DebugBreak();
    231   }
    232   abort();
    233 }
    234 
    235 
    236 void OS::DebugBreak() {
    237 #if V8_HOST_ARCH_ARM
    238   asm("bkpt 0");
    239 #elif V8_HOST_ARCH_MIPS
    240   asm("break");
    241 #elif V8_HOST_ARCH_IA32
    242 #if defined(__native_client__)
    243   asm("hlt");
    244 #else
    245   asm("int $3");
    246 #endif  // __native_client__
    247 #elif V8_HOST_ARCH_X64
    248   asm("int $3");
    249 #else
    250 #error Unsupported host architecture.
    251 #endif
    252 }
    253 
    254 
    255 // ----------------------------------------------------------------------------
    256 // Math functions
    257 
    258 double ceiling(double x) {
    259   // Correct buggy 'ceil' on some systems (i.e. FreeBSD, OS X 10.5)
    260   return (-1.0 < x && x < 0.0) ? -0.0 : ceil(x);
    261 }
    262 
    263 
    264 double modulo(double x, double y) {
    265   return fmod(x, y);
    266 }
    267 
    268 
    269 #define UNARY_MATH_FUNCTION(name, generator)             \
    270 static UnaryMathFunction fast_##name##_function = NULL;  \
    271 void init_fast_##name##_function() {                     \
    272   fast_##name##_function = generator;                    \
    273 }                                                        \
    274 double fast_##name(double x) {                           \
    275   return (*fast_##name##_function)(x);                   \
    276 }
    277 
    278 UNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN))
    279 UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS))
    280 UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN))
    281 UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG))
    282 UNARY_MATH_FUNCTION(exp, CreateExpFunction())
    283 UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
    284 
    285 #undef UNARY_MATH_FUNCTION
    286 
    287 
    288 void lazily_initialize_fast_exp() {
    289   if (fast_exp_function == NULL) {
    290     init_fast_exp_function();
    291   }
    292 }
    293 
    294 
    295 double OS::nan_value() {
    296   // NAN from math.h is defined in C99 and not in POSIX.
    297   return NAN;
    298 }
    299 
    300 
    301 int OS::GetCurrentProcessId() {
    302   return static_cast<int>(getpid());
    303 }
    304 
    305 
    306 // ----------------------------------------------------------------------------
    307 // POSIX date/time support.
    308 //
    309 
    310 int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
    311   struct rusage usage;
    312 
    313   if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
    314   *secs = usage.ru_utime.tv_sec;
    315   *usecs = usage.ru_utime.tv_usec;
    316   return 0;
    317 }
    318 
    319 
    320 double OS::TimeCurrentMillis() {
    321   struct timeval tv;
    322   if (gettimeofday(&tv, NULL) < 0) return 0.0;
    323   return (static_cast<double>(tv.tv_sec) * 1000) +
    324          (static_cast<double>(tv.tv_usec) / 1000);
    325 }
    326 
    327 
    328 int64_t OS::Ticks() {
    329   // gettimeofday has microsecond resolution.
    330   struct timeval tv;
    331   if (gettimeofday(&tv, NULL) < 0)
    332     return 0;
    333   return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
    334 }
    335 
    336 
    337 double OS::DaylightSavingsOffset(double time) {
    338   if (std::isnan(time)) return nan_value();
    339   time_t tv = static_cast<time_t>(floor(time/msPerSecond));
    340   struct tm* t = localtime(&tv);
    341   if (NULL == t) return nan_value();
    342   return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
    343 }
    344 
    345 
    346 int OS::GetLastError() {
    347   return errno;
    348 }
    349 
    350 
    351 // ----------------------------------------------------------------------------
    352 // POSIX stdio support.
    353 //
    354 
    355 FILE* OS::FOpen(const char* path, const char* mode) {
    356   FILE* file = fopen(path, mode);
    357   if (file == NULL) return NULL;
    358   struct stat file_stat;
    359   if (fstat(fileno(file), &file_stat) != 0) return NULL;
    360   bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
    361   if (is_regular_file) return file;
    362   fclose(file);
    363   return NULL;
    364 }
    365 
    366 
    367 bool OS::Remove(const char* path) {
    368   return (remove(path) == 0);
    369 }
    370 
    371 
    372 FILE* OS::OpenTemporaryFile() {
    373   return tmpfile();
    374 }
    375 
    376 
    377 const char* const OS::LogFileOpenMode = "w";
    378 
    379 
    380 void OS::Print(const char* format, ...) {
    381   va_list args;
    382   va_start(args, format);
    383   VPrint(format, args);
    384   va_end(args);
    385 }
    386 
    387 
    388 void OS::VPrint(const char* format, va_list args) {
    389 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
    390   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
    391 #else
    392   vprintf(format, args);
    393 #endif
    394 }
    395 
    396 
    397 void OS::FPrint(FILE* out, const char* format, ...) {
    398   va_list args;
    399   va_start(args, format);
    400   VFPrint(out, format, args);
    401   va_end(args);
    402 }
    403 
    404 
    405 void OS::VFPrint(FILE* out, const char* format, va_list args) {
    406 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
    407   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
    408 #else
    409   vfprintf(out, format, args);
    410 #endif
    411 }
    412 
    413 
    414 void OS::PrintError(const char* format, ...) {
    415   va_list args;
    416   va_start(args, format);
    417   VPrintError(format, args);
    418   va_end(args);
    419 }
    420 
    421 
    422 void OS::VPrintError(const char* format, va_list args) {
    423 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
    424   __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
    425 #else
    426   vfprintf(stderr, format, args);
    427 #endif
    428 }
    429 
    430 
    431 int OS::SNPrintF(Vector<char> str, const char* format, ...) {
    432   va_list args;
    433   va_start(args, format);
    434   int result = VSNPrintF(str, format, args);
    435   va_end(args);
    436   return result;
    437 }
    438 
    439 
    440 int OS::VSNPrintF(Vector<char> str,
    441                   const char* format,
    442                   va_list args) {
    443   int n = vsnprintf(str.start(), str.length(), format, args);
    444   if (n < 0 || n >= str.length()) {
    445     // If the length is zero, the assignment fails.
    446     if (str.length() > 0)
    447       str[str.length() - 1] = '\0';
    448     return -1;
    449   } else {
    450     return n;
    451   }
    452 }
    453 
    454 
    455 #if V8_TARGET_ARCH_IA32
    456 static void MemMoveWrapper(void* dest, const void* src, size_t size) {
    457   memmove(dest, src, size);
    458 }
    459 
    460 
    461 // Initialize to library version so we can call this at any time during startup.
    462 static OS::MemMoveFunction memmove_function = &MemMoveWrapper;
    463 
    464 // Defined in codegen-ia32.cc.
    465 OS::MemMoveFunction CreateMemMoveFunction();
    466 
    467 // Copy memory area. No restrictions.
    468 void OS::MemMove(void* dest, const void* src, size_t size) {
    469   if (size == 0) return;
    470   // Note: here we rely on dependent reads being ordered. This is true
    471   // on all architectures we currently support.
    472   (*memmove_function)(dest, src, size);
    473 }
    474 
    475 #elif defined(V8_HOST_ARCH_ARM)
    476 void OS::MemCopyUint16Uint8Wrapper(uint16_t* dest,
    477                                const uint8_t* src,
    478                                size_t chars) {
    479   uint16_t *limit = dest + chars;
    480   while (dest < limit) {
    481     *dest++ = static_cast<uint16_t>(*src++);
    482   }
    483 }
    484 
    485 
    486 OS::MemCopyUint8Function OS::memcopy_uint8_function = &OS::MemCopyUint8Wrapper;
    487 OS::MemCopyUint16Uint8Function OS::memcopy_uint16_uint8_function =
    488     &OS::MemCopyUint16Uint8Wrapper;
    489 // Defined in codegen-arm.cc.
    490 OS::MemCopyUint8Function CreateMemCopyUint8Function(
    491     OS::MemCopyUint8Function stub);
    492 OS::MemCopyUint16Uint8Function CreateMemCopyUint16Uint8Function(
    493     OS::MemCopyUint16Uint8Function stub);
    494 #endif
    495 
    496 
    497 void OS::PostSetUp() {
    498 #if V8_TARGET_ARCH_IA32
    499   OS::MemMoveFunction generated_memmove = CreateMemMoveFunction();
    500   if (generated_memmove != NULL) {
    501     memmove_function = generated_memmove;
    502   }
    503 #elif defined(V8_HOST_ARCH_ARM)
    504   OS::memcopy_uint8_function =
    505       CreateMemCopyUint8Function(&OS::MemCopyUint8Wrapper);
    506   OS::memcopy_uint16_uint8_function =
    507       CreateMemCopyUint16Uint8Function(&OS::MemCopyUint16Uint8Wrapper);
    508 #endif
    509   init_fast_sin_function();
    510   init_fast_cos_function();
    511   init_fast_tan_function();
    512   init_fast_log_function();
    513   // fast_exp is initialized lazily.
    514   init_fast_sqrt_function();
    515 }
    516 
    517 
    518 // ----------------------------------------------------------------------------
    519 // POSIX string support.
    520 //
    521 
    522 char* OS::StrChr(char* str, int c) {
    523   return strchr(str, c);
    524 }
    525 
    526 
    527 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
    528   strncpy(dest.start(), src, n);
    529 }
    530 
    531 
    532 // ----------------------------------------------------------------------------
    533 // POSIX thread support.
    534 //
    535 
    536 class Thread::PlatformData : public Malloced {
    537  public:
    538   PlatformData() : thread_(kNoThread) {}
    539   pthread_t thread_;  // Thread handle for pthread.
    540 };
    541 
    542 Thread::Thread(const Options& options)
    543     : data_(new PlatformData),
    544       stack_size_(options.stack_size()),
    545       start_semaphore_(NULL) {
    546   set_name(options.name());
    547 }
    548 
    549 
    550 Thread::~Thread() {
    551   delete data_;
    552 }
    553 
    554 
    555 static void SetThreadName(const char* name) {
    556 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
    557   pthread_set_name_np(pthread_self(), name);
    558 #elif defined(__NetBSD__)
    559   STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP);
    560   pthread_setname_np(pthread_self(), "%s", name);
    561 #elif defined(__APPLE__)
    562   // pthread_setname_np is only available in 10.6 or later, so test
    563   // for it at runtime.
    564   int (*dynamic_pthread_setname_np)(const char*);
    565   *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
    566     dlsym(RTLD_DEFAULT, "pthread_setname_np");
    567   if (dynamic_pthread_setname_np == NULL)
    568     return;
    569 
    570   // Mac OS X does not expose the length limit of the name, so hardcode it.
    571   static const int kMaxNameLength = 63;
    572   STATIC_ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength);
    573   dynamic_pthread_setname_np(name);
    574 #elif defined(PR_SET_NAME)
    575   prctl(PR_SET_NAME,
    576         reinterpret_cast<unsigned long>(name),  // NOLINT
    577         0, 0, 0);
    578 #endif
    579 }
    580 
    581 
    582 static void* ThreadEntry(void* arg) {
    583   Thread* thread = reinterpret_cast<Thread*>(arg);
    584   // This is also initialized by the first argument to pthread_create() but we
    585   // don't know which thread will run first (the original thread or the new
    586   // one) so we initialize it here too.
    587   thread->data()->thread_ = pthread_self();
    588   SetThreadName(thread->name());
    589   ASSERT(thread->data()->thread_ != kNoThread);
    590   thread->NotifyStartedAndRun();
    591   return NULL;
    592 }
    593 
    594 
    595 void Thread::set_name(const char* name) {
    596   strncpy(name_, name, sizeof(name_));
    597   name_[sizeof(name_) - 1] = '\0';
    598 }
    599 
    600 
    601 void Thread::Start() {
    602   int result;
    603   pthread_attr_t attr;
    604   memset(&attr, 0, sizeof(attr));
    605   result = pthread_attr_init(&attr);
    606   ASSERT_EQ(0, result);
    607   // Native client uses default stack size.
    608 #if !defined(__native_client__)
    609   if (stack_size_ > 0) {
    610     result = pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
    611     ASSERT_EQ(0, result);
    612   }
    613 #endif
    614   result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
    615   ASSERT_EQ(0, result);
    616   result = pthread_attr_destroy(&attr);
    617   ASSERT_EQ(0, result);
    618   ASSERT(data_->thread_ != kNoThread);
    619   USE(result);
    620 }
    621 
    622 
    623 void Thread::Join() {
    624   pthread_join(data_->thread_, NULL);
    625 }
    626 
    627 
    628 void Thread::YieldCPU() {
    629   int result = sched_yield();
    630   ASSERT_EQ(0, result);
    631   USE(result);
    632 }
    633 
    634 
    635 static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
    636 #if defined(__CYGWIN__)
    637   // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
    638   // because pthread_key_t is a pointer type on Cygwin. This will probably not
    639   // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
    640   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
    641   intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key);
    642   return static_cast<Thread::LocalStorageKey>(ptr_key);
    643 #else
    644   return static_cast<Thread::LocalStorageKey>(pthread_key);
    645 #endif
    646 }
    647 
    648 
    649 static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
    650 #if defined(__CYGWIN__)
    651   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
    652   intptr_t ptr_key = static_cast<intptr_t>(local_key);
    653   return reinterpret_cast<pthread_key_t>(ptr_key);
    654 #else
    655   return static_cast<pthread_key_t>(local_key);
    656 #endif
    657 }
    658 
    659 
    660 #ifdef V8_FAST_TLS_SUPPORTED
    661 
    662 static Atomic32 tls_base_offset_initialized = 0;
    663 intptr_t kMacTlsBaseOffset = 0;
    664 
    665 // It's safe to do the initialization more that once, but it has to be
    666 // done at least once.
    667 static void InitializeTlsBaseOffset() {
    668   const size_t kBufferSize = 128;
    669   char buffer[kBufferSize];
    670   size_t buffer_size = kBufferSize;
    671   int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
    672   if (sysctl(ctl_name, 2, buffer, &buffer_size, NULL, 0) != 0) {
    673     V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
    674   }
    675   // The buffer now contains a string of the form XX.YY.ZZ, where
    676   // XX is the major kernel version component.
    677   // Make sure the buffer is 0-terminated.
    678   buffer[kBufferSize - 1] = '\0';
    679   char* period_pos = strchr(buffer, '.');
    680   *period_pos = '\0';
    681   int kernel_version_major =
    682       static_cast<int>(strtol(buffer, NULL, 10));  // NOLINT
    683   // The constants below are taken from pthreads.s from the XNU kernel
    684   // sources archive at www.opensource.apple.com.
    685   if (kernel_version_major < 11) {
    686     // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the
    687     // same offsets.
    688 #if V8_HOST_ARCH_IA32
    689     kMacTlsBaseOffset = 0x48;
    690 #else
    691     kMacTlsBaseOffset = 0x60;
    692 #endif
    693   } else {
    694     // 11.x.x (Lion) changed the offset.
    695     kMacTlsBaseOffset = 0;
    696   }
    697 
    698   Release_Store(&tls_base_offset_initialized, 1);
    699 }
    700 
    701 
    702 static void CheckFastTls(Thread::LocalStorageKey key) {
    703   void* expected = reinterpret_cast<void*>(0x1234CAFE);
    704   Thread::SetThreadLocal(key, expected);
    705   void* actual = Thread::GetExistingThreadLocal(key);
    706   if (expected != actual) {
    707     V8_Fatal(__FILE__, __LINE__,
    708              "V8 failed to initialize fast TLS on current kernel");
    709   }
    710   Thread::SetThreadLocal(key, NULL);
    711 }
    712 
    713 #endif  // V8_FAST_TLS_SUPPORTED
    714 
    715 
    716 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
    717 #ifdef V8_FAST_TLS_SUPPORTED
    718   bool check_fast_tls = false;
    719   if (tls_base_offset_initialized == 0) {
    720     check_fast_tls = true;
    721     InitializeTlsBaseOffset();
    722   }
    723 #endif
    724   pthread_key_t key;
    725   int result = pthread_key_create(&key, NULL);
    726   ASSERT_EQ(0, result);
    727   USE(result);
    728   LocalStorageKey local_key = PthreadKeyToLocalKey(key);
    729 #ifdef V8_FAST_TLS_SUPPORTED
    730   // If we just initialized fast TLS support, make sure it works.
    731   if (check_fast_tls) CheckFastTls(local_key);
    732 #endif
    733   return local_key;
    734 }
    735 
    736 
    737 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
    738   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
    739   int result = pthread_key_delete(pthread_key);
    740   ASSERT_EQ(0, result);
    741   USE(result);
    742 }
    743 
    744 
    745 void* Thread::GetThreadLocal(LocalStorageKey key) {
    746   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
    747   return pthread_getspecific(pthread_key);
    748 }
    749 
    750 
    751 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
    752   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
    753   int result = pthread_setspecific(pthread_key, value);
    754   ASSERT_EQ(0, result);
    755   USE(result);
    756 }
    757 
    758 
    759 class POSIXMutex : public Mutex {
    760  public:
    761   POSIXMutex() {
    762     pthread_mutexattr_t attr;
    763     memset(&attr, 0, sizeof(attr));
    764     int result = pthread_mutexattr_init(&attr);
    765     ASSERT(result == 0);
    766     result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    767     ASSERT(result == 0);
    768     result = pthread_mutex_init(&mutex_, &attr);
    769     ASSERT(result == 0);
    770     result = pthread_mutexattr_destroy(&attr);
    771     ASSERT(result == 0);
    772     USE(result);
    773   }
    774 
    775   virtual ~POSIXMutex() { pthread_mutex_destroy(&mutex_); }
    776 
    777   virtual int Lock() { return pthread_mutex_lock(&mutex_); }
    778 
    779   virtual int Unlock() { return pthread_mutex_unlock(&mutex_); }
    780 
    781   virtual bool TryLock() {
    782     int result = pthread_mutex_trylock(&mutex_);
    783     // Return false if the lock is busy and locking failed.
    784     if (result == EBUSY) {
    785       return false;
    786     }
    787     ASSERT(result == 0);  // Verify no other errors.
    788     return true;
    789   }
    790 
    791  private:
    792   pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
    793 };
    794 
    795 
    796 Mutex* OS::CreateMutex() {
    797   return new POSIXMutex();
    798 }
    799 
    800 
    801 // ----------------------------------------------------------------------------
    802 // POSIX socket support.
    803 //
    804 
    805 class POSIXSocket : public Socket {
    806  public:
    807   explicit POSIXSocket() {
    808     // Create the socket.
    809     socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    810     if (IsValid()) {
    811       // Allow rapid reuse.
    812       static const int kOn = 1;
    813       int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
    814                            &kOn, sizeof(kOn));
    815       ASSERT(ret == 0);
    816       USE(ret);
    817     }
    818   }
    819   explicit POSIXSocket(int socket): socket_(socket) { }
    820   virtual ~POSIXSocket() { Shutdown(); }
    821 
    822   // Server initialization.
    823   bool Bind(const int port);
    824   bool Listen(int backlog) const;
    825   Socket* Accept() const;
    826 
    827   // Client initialization.
    828   bool Connect(const char* host, const char* port);
    829 
    830   // Shutdown socket for both read and write.
    831   bool Shutdown();
    832 
    833   // Data Transimission
    834   int Send(const char* data, int len) const;
    835   int Receive(char* data, int len) const;
    836 
    837   bool SetReuseAddress(bool reuse_address);
    838 
    839   bool IsValid() const { return socket_ != -1; }
    840 
    841  private:
    842   int socket_;
    843 };
    844 
    845 
    846 bool POSIXSocket::Bind(const int port) {
    847   if (!IsValid())  {
    848     return false;
    849   }
    850 
    851   sockaddr_in addr;
    852   memset(&addr, 0, sizeof(addr));
    853   addr.sin_family = AF_INET;
    854   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    855   addr.sin_port = htons(port);
    856   int status = bind(socket_,
    857                     BitCast<struct sockaddr *>(&addr),
    858                     sizeof(addr));
    859   return status == 0;
    860 }
    861 
    862 
    863 bool POSIXSocket::Listen(int backlog) const {
    864   if (!IsValid()) {
    865     return false;
    866   }
    867 
    868   int status = listen(socket_, backlog);
    869   return status == 0;
    870 }
    871 
    872 
    873 Socket* POSIXSocket::Accept() const {
    874   if (!IsValid()) {
    875     return NULL;
    876   }
    877 
    878   int socket;
    879   do {
    880     socket = accept(socket_, NULL, NULL);
    881   } while (socket == -1 && errno == EINTR);
    882 
    883   if (socket == -1) {
    884     return NULL;
    885   } else {
    886     return new POSIXSocket(socket);
    887   }
    888 }
    889 
    890 
    891 bool POSIXSocket::Connect(const char* host, const char* port) {
    892   if (!IsValid()) {
    893     return false;
    894   }
    895 
    896   // Lookup host and port.
    897   struct addrinfo *result = NULL;
    898   struct addrinfo hints;
    899   memset(&hints, 0, sizeof(addrinfo));
    900   hints.ai_family = AF_INET;
    901   hints.ai_socktype = SOCK_STREAM;
    902   hints.ai_protocol = IPPROTO_TCP;
    903   int status = getaddrinfo(host, port, &hints, &result);
    904   if (status != 0) {
    905     return false;
    906   }
    907 
    908   // Connect.
    909   do {
    910     status = connect(socket_, result->ai_addr, result->ai_addrlen);
    911   } while (status == -1 && errno == EINTR);
    912   freeaddrinfo(result);
    913   return status == 0;
    914 }
    915 
    916 
    917 bool POSIXSocket::Shutdown() {
    918   if (IsValid()) {
    919     // Shutdown socket for both read and write.
    920     int status = shutdown(socket_, SHUT_RDWR);
    921     close(socket_);
    922     socket_ = -1;
    923     return status == 0;
    924   }
    925   return true;
    926 }
    927 
    928 
    929 int POSIXSocket::Send(const char* data, int len) const {
    930   if (len <= 0) return 0;
    931   int written = 0;
    932   while (written < len) {
    933     int status = send(socket_, data + written, len - written, 0);
    934     if (status == 0) {
    935       break;
    936     } else if (status > 0) {
    937       written += status;
    938     } else if (errno != EINTR) {
    939       return 0;
    940     }
    941   }
    942   return written;
    943 }
    944 
    945 
    946 int POSIXSocket::Receive(char* data, int len) const {
    947   if (len <= 0) return 0;
    948   int status;
    949   do {
    950     status = recv(socket_, data, len, 0);
    951   } while (status == -1 && errno == EINTR);
    952   return (status < 0) ? 0 : status;
    953 }
    954 
    955 
    956 bool POSIXSocket::SetReuseAddress(bool reuse_address) {
    957   int on = reuse_address ? 1 : 0;
    958   int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    959   return status == 0;
    960 }
    961 
    962 
    963 bool Socket::SetUp() {
    964   // Nothing to do on POSIX.
    965   return true;
    966 }
    967 
    968 
    969 int Socket::LastError() {
    970   return errno;
    971 }
    972 
    973 
    974 uint16_t Socket::HToN(uint16_t value) {
    975   return htons(value);
    976 }
    977 
    978 
    979 uint16_t Socket::NToH(uint16_t value) {
    980   return ntohs(value);
    981 }
    982 
    983 
    984 uint32_t Socket::HToN(uint32_t value) {
    985   return htonl(value);
    986 }
    987 
    988 
    989 uint32_t Socket::NToH(uint32_t value) {
    990   return ntohl(value);
    991 }
    992 
    993 
    994 Socket* OS::CreateSocket() {
    995   return new POSIXSocket();
    996 }
    997 
    998 
    999 } }  // namespace v8::internal
   1000