deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / base / platform / platform-posix.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Platform-specific code for POSIX goes here. This is not a platform on its
6 // own, but contains the parts which are the same across the POSIX platforms
7 // Linux, MacOS, FreeBSD, OpenBSD, NetBSD and QNX.
8
9 #include <errno.h>
10 #include <limits.h>
11 #include <pthread.h>
12 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
13 #include <pthread_np.h>  // for pthread_set_name_np
14 #endif
15 #include <sched.h>  // for sched_yield
16 #include <stdio.h>
17 #include <time.h>
18 #include <unistd.h>
19
20 #include <sys/mman.h>
21 #include <sys/resource.h>
22 #include <sys/stat.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
26     defined(__NetBSD__) || defined(__OpenBSD__)
27 #include <sys/sysctl.h>  // NOLINT, for sysctl
28 #endif
29
30 #undef MAP_TYPE
31
32 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
33 #define LOG_TAG "v8"
34 #include <android/log.h>  // NOLINT
35 #endif
36
37 #include <cmath>
38 #include <cstdlib>
39
40 #include "src/base/lazy-instance.h"
41 #include "src/base/macros.h"
42 #include "src/base/platform/platform.h"
43 #include "src/base/platform/time.h"
44 #include "src/base/utils/random-number-generator.h"
45
46 #ifdef V8_FAST_TLS_SUPPORTED
47 #include "src/base/atomicops.h"
48 #endif
49
50 #if V8_OS_MACOSX
51 #include <dlfcn.h>
52 #endif
53
54 #if V8_OS_LINUX
55 #include <sys/prctl.h>  // NOLINT, for prctl
56 #endif
57
58 #if !defined(V8_OS_NACL) && !defined(_AIX)
59 #include <sys/syscall.h>
60 #endif
61
62 namespace v8 {
63 namespace base {
64
65 namespace {
66
67 // 0 is never a valid thread id.
68 const pthread_t kNoThread = (pthread_t) 0;
69
70 bool g_hard_abort = false;
71
72 const char* g_gc_fake_mmap = NULL;
73
74 }  // namespace
75
76
77 int OS::ActivationFrameAlignment() {
78 #if V8_TARGET_ARCH_ARM
79   // On EABI ARM targets this is required for fp correctness in the
80   // runtime system.
81   return 8;
82 #elif V8_TARGET_ARCH_MIPS
83   return 8;
84 #else
85   // Otherwise we just assume 16 byte alignment, i.e.:
86   // - With gcc 4.4 the tree vectorization optimizer can generate code
87   //   that requires 16 byte alignment such as movdqa on x86.
88   // - Mac OS X, PPC and Solaris (64-bit) activation frames must
89   //   be 16 byte-aligned;  see "Mac OS X ABI Function Call Guide"
90   return 16;
91 #endif
92 }
93
94
95 intptr_t OS::CommitPageSize() {
96   static intptr_t page_size = getpagesize();
97   return page_size;
98 }
99
100
101 void OS::Free(void* address, const size_t size) {
102   // TODO(1240712): munmap has a return value which is ignored here.
103   int result = munmap(address, size);
104   USE(result);
105   DCHECK(result == 0);
106 }
107
108
109 // Get rid of writable permission on code allocations.
110 void OS::ProtectCode(void* address, const size_t size) {
111 #if V8_OS_CYGWIN
112   DWORD old_protect;
113   VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
114 #elif V8_OS_NACL
115   // The Native Client port of V8 uses an interpreter, so
116   // code pages don't need PROT_EXEC.
117   mprotect(address, size, PROT_READ);
118 #else
119   mprotect(address, size, PROT_READ | PROT_EXEC);
120 #endif
121 }
122
123
124 // Create guard pages.
125 void OS::Guard(void* address, const size_t size) {
126 #if V8_OS_CYGWIN
127   DWORD oldprotect;
128   VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect);
129 #else
130   mprotect(address, size, PROT_NONE);
131 #endif
132 }
133
134
135 static LazyInstance<RandomNumberGenerator>::type
136     platform_random_number_generator = LAZY_INSTANCE_INITIALIZER;
137
138
139 void OS::Initialize(int64_t random_seed, bool hard_abort,
140                     const char* const gc_fake_mmap) {
141   if (random_seed) {
142     platform_random_number_generator.Pointer()->SetSeed(random_seed);
143   }
144   g_hard_abort = hard_abort;
145   g_gc_fake_mmap = gc_fake_mmap;
146 }
147
148
149 const char* OS::GetGCFakeMMapFile() {
150   return g_gc_fake_mmap;
151 }
152
153
154 void* OS::GetRandomMmapAddr() {
155 #if V8_OS_NACL
156   // TODO(bradchen): restore randomization once Native Client gets
157   // smarter about using mmap address hints.
158   // See http://code.google.com/p/nativeclient/issues/3341
159   return NULL;
160 #endif
161 #if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
162     defined(THREAD_SANITIZER)
163   // Dynamic tools do not support custom mmap addresses.
164   return NULL;
165 #endif
166   uintptr_t raw_addr;
167   platform_random_number_generator.Pointer()->NextBytes(&raw_addr,
168                                                         sizeof(raw_addr));
169 #if V8_TARGET_ARCH_X64
170   // Currently available CPUs have 48 bits of virtual addressing.  Truncate
171   // the hint address to 46 bits to give the kernel a fighting chance of
172   // fulfilling our placement request.
173   raw_addr &= V8_UINT64_C(0x3ffffffff000);
174 #elif V8_TARGET_ARCH_PPC64
175 #if V8_OS_AIX
176   // AIX: 64 bits of virtual addressing, but we limit address range to:
177   //   a) minimize Segment Lookaside Buffer (SLB) misses and
178   raw_addr &= V8_UINT64_C(0x3ffff000);
179   // Use extra address space to isolate the mmap regions.
180   raw_addr += V8_UINT64_C(0x400000000000);
181 #elif V8_TARGET_BIG_ENDIAN
182   // Big-endian Linux: 44 bits of virtual addressing.
183   raw_addr &= V8_UINT64_C(0x03fffffff000);
184 #else
185   // Little-endian Linux: 48 bits of virtual addressing.
186   raw_addr &= V8_UINT64_C(0x3ffffffff000);
187 #endif
188 #else
189   raw_addr &= 0x3ffff000;
190
191 # ifdef __sun
192   // For our Solaris/illumos mmap hint, we pick a random address in the bottom
193   // half of the top half of the address space (that is, the third quarter).
194   // Because we do not MAP_FIXED, this will be treated only as a hint -- the
195   // system will not fail to mmap() because something else happens to already
196   // be mapped at our random address. We deliberately set the hint high enough
197   // to get well above the system's break (that is, the heap); Solaris and
198   // illumos will try the hint and if that fails allocate as if there were
199   // no hint at all. The high hint prevents the break from getting hemmed in
200   // at low values, ceding half of the address space to the system heap.
201   raw_addr += 0x80000000;
202 #elif V8_OS_AIX
203   // The range 0x30000000 - 0xD0000000 is available on AIX;
204   // choose the upper range.
205   raw_addr += 0x90000000;
206 # else
207   // The range 0x20000000 - 0x60000000 is relatively unpopulated across a
208   // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
209   // 10.6 and 10.7.
210   raw_addr += 0x20000000;
211 # endif
212 #endif
213   return reinterpret_cast<void*>(raw_addr);
214 }
215
216
217 size_t OS::AllocateAlignment() {
218   return static_cast<size_t>(sysconf(_SC_PAGESIZE));
219 }
220
221
222 void OS::Sleep(int milliseconds) {
223   useconds_t ms = static_cast<useconds_t>(milliseconds);
224   usleep(1000 * ms);
225 }
226
227
228 void OS::Abort() {
229   if (g_hard_abort) {
230     V8_IMMEDIATE_CRASH();
231   }
232   // Redirect to std abort to signal abnormal program termination.
233   abort();
234 }
235
236
237 void OS::DebugBreak() {
238 #if V8_HOST_ARCH_ARM
239   asm("bkpt 0");
240 #elif V8_HOST_ARCH_ARM64
241   asm("brk 0");
242 #elif V8_HOST_ARCH_MIPS
243   asm("break");
244 #elif V8_HOST_ARCH_MIPS64
245   asm("break");
246 #elif V8_HOST_ARCH_PPC
247   asm("twge 2,2");
248 #elif V8_HOST_ARCH_IA32
249 #if V8_OS_NACL
250   asm("hlt");
251 #else
252   asm("int $3");
253 #endif  // V8_OS_NACL
254 #elif V8_HOST_ARCH_X64
255   asm("int $3");
256 #else
257 #error Unsupported host architecture.
258 #endif
259 }
260
261
262 int OS::GetCurrentProcessId() {
263   return static_cast<int>(getpid());
264 }
265
266
267 int OS::GetCurrentThreadId() {
268 #if V8_OS_MACOSX || (V8_OS_ANDROID && defined(__APPLE__))
269   return static_cast<int>(pthread_mach_thread_np(pthread_self()));
270 #elif V8_OS_LINUX
271   return static_cast<int>(syscall(__NR_gettid));
272 #elif V8_OS_ANDROID
273   return static_cast<int>(gettid());
274 #elif V8_OS_AIX
275   return static_cast<int>(thread_self());
276 #elif V8_OS_SOLARIS
277   return static_cast<int>(pthread_self());
278 #else
279   return static_cast<int>(reinterpret_cast<intptr_t>(pthread_self()));
280 #endif
281 }
282
283
284 // ----------------------------------------------------------------------------
285 // POSIX date/time support.
286 //
287
288 int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
289 #if V8_OS_NACL
290   // Optionally used in Logger::ResourceEvent.
291   return -1;
292 #else
293   struct rusage usage;
294
295   if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
296   *secs = usage.ru_utime.tv_sec;
297   *usecs = usage.ru_utime.tv_usec;
298   return 0;
299 #endif
300 }
301
302
303 double OS::TimeCurrentMillis() {
304   return Time::Now().ToJsTime();
305 }
306
307
308 class TimezoneCache {};
309
310
311 TimezoneCache* OS::CreateTimezoneCache() {
312   return NULL;
313 }
314
315
316 void OS::DisposeTimezoneCache(TimezoneCache* cache) {
317   DCHECK(cache == NULL);
318 }
319
320
321 void OS::ClearTimezoneCache(TimezoneCache* cache) {
322   DCHECK(cache == NULL);
323 }
324
325
326 double OS::DaylightSavingsOffset(double time, TimezoneCache*) {
327   if (std::isnan(time)) return std::numeric_limits<double>::quiet_NaN();
328   time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
329   struct tm* t = localtime(&tv);
330   if (NULL == t) return std::numeric_limits<double>::quiet_NaN();
331   return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
332 }
333
334
335 int OS::GetLastError() {
336   return errno;
337 }
338
339
340 // ----------------------------------------------------------------------------
341 // POSIX stdio support.
342 //
343
344 FILE* OS::FOpen(const char* path, const char* mode) {
345   FILE* file = fopen(path, mode);
346   if (file == NULL) return NULL;
347   struct stat file_stat;
348   if (fstat(fileno(file), &file_stat) != 0) return NULL;
349   bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
350   if (is_regular_file) return file;
351   fclose(file);
352   return NULL;
353 }
354
355
356 bool OS::Remove(const char* path) {
357   return (remove(path) == 0);
358 }
359
360
361 bool OS::isDirectorySeparator(const char ch) {
362   return ch == '/';
363 }
364
365
366 FILE* OS::OpenTemporaryFile() {
367   return tmpfile();
368 }
369
370
371 const char* const OS::LogFileOpenMode = "w";
372
373
374 void OS::Print(const char* format, ...) {
375   va_list args;
376   va_start(args, format);
377   VPrint(format, args);
378   va_end(args);
379 }
380
381
382 void OS::VPrint(const char* format, va_list args) {
383 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
384   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
385 #else
386   vprintf(format, args);
387 #endif
388 }
389
390
391 void OS::FPrint(FILE* out, const char* format, ...) {
392   va_list args;
393   va_start(args, format);
394   VFPrint(out, format, args);
395   va_end(args);
396 }
397
398
399 void OS::VFPrint(FILE* out, const char* format, va_list args) {
400 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
401   __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args);
402 #else
403   vfprintf(out, format, args);
404 #endif
405 }
406
407
408 void OS::PrintError(const char* format, ...) {
409   va_list args;
410   va_start(args, format);
411   VPrintError(format, args);
412   va_end(args);
413 }
414
415
416 void OS::VPrintError(const char* format, va_list args) {
417 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
418   __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args);
419 #else
420   vfprintf(stderr, format, args);
421 #endif
422 }
423
424
425 int OS::SNPrintF(char* str, int length, const char* format, ...) {
426   va_list args;
427   va_start(args, format);
428   int result = VSNPrintF(str, length, format, args);
429   va_end(args);
430   return result;
431 }
432
433
434 int OS::VSNPrintF(char* str,
435                   int length,
436                   const char* format,
437                   va_list args) {
438   int n = vsnprintf(str, length, format, args);
439   if (n < 0 || n >= length) {
440     // If the length is zero, the assignment fails.
441     if (length > 0)
442       str[length - 1] = '\0';
443     return -1;
444   } else {
445     return n;
446   }
447 }
448
449
450 // ----------------------------------------------------------------------------
451 // POSIX string support.
452 //
453
454 char* OS::StrChr(char* str, int c) {
455   return strchr(str, c);
456 }
457
458
459 void OS::StrNCpy(char* dest, int length, const char* src, size_t n) {
460   strncpy(dest, src, n);
461 }
462
463
464 // ----------------------------------------------------------------------------
465 // POSIX thread support.
466 //
467
468 class Thread::PlatformData {
469  public:
470   PlatformData() : thread_(kNoThread) {}
471   pthread_t thread_;  // Thread handle for pthread.
472   // Synchronizes thread creation
473   Mutex thread_creation_mutex_;
474 };
475
476 Thread::Thread(const Options& options)
477     : data_(new PlatformData),
478       stack_size_(options.stack_size()),
479       start_semaphore_(NULL) {
480   if (stack_size_ > 0 && static_cast<size_t>(stack_size_) < PTHREAD_STACK_MIN) {
481     stack_size_ = PTHREAD_STACK_MIN;
482   }
483   set_name(options.name());
484 }
485
486
487 Thread::~Thread() {
488   delete data_;
489 }
490
491
492 static void SetThreadName(const char* name) {
493 #if V8_OS_DRAGONFLYBSD || V8_OS_FREEBSD || V8_OS_OPENBSD
494   pthread_set_name_np(pthread_self(), name);
495 #elif V8_OS_NETBSD
496   STATIC_ASSERT(Thread::kMaxThreadNameLength <= PTHREAD_MAX_NAMELEN_NP);
497   pthread_setname_np(pthread_self(), "%s", name);
498 #elif V8_OS_MACOSX
499   // pthread_setname_np is only available in 10.6 or later, so test
500   // for it at runtime.
501   int (*dynamic_pthread_setname_np)(const char*);
502   *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
503     dlsym(RTLD_DEFAULT, "pthread_setname_np");
504   if (dynamic_pthread_setname_np == NULL)
505     return;
506
507   // Mac OS X does not expose the length limit of the name, so hardcode it.
508   static const int kMaxNameLength = 63;
509   STATIC_ASSERT(Thread::kMaxThreadNameLength <= kMaxNameLength);
510   dynamic_pthread_setname_np(name);
511 #elif defined(PR_SET_NAME)
512   prctl(PR_SET_NAME,
513         reinterpret_cast<unsigned long>(name),  // NOLINT
514         0, 0, 0);
515 #endif
516 }
517
518
519 static void* ThreadEntry(void* arg) {
520   Thread* thread = reinterpret_cast<Thread*>(arg);
521   // We take the lock here to make sure that pthread_create finished first since
522   // we don't know which thread will run first (the original thread or the new
523   // one).
524   { LockGuard<Mutex> lock_guard(&thread->data()->thread_creation_mutex_); }
525   SetThreadName(thread->name());
526   DCHECK(thread->data()->thread_ != kNoThread);
527   thread->NotifyStartedAndRun();
528   return NULL;
529 }
530
531
532 void Thread::set_name(const char* name) {
533   strncpy(name_, name, sizeof(name_));
534   name_[sizeof(name_) - 1] = '\0';
535 }
536
537
538 void Thread::Start() {
539   int result;
540   pthread_attr_t attr;
541   memset(&attr, 0, sizeof(attr));
542   result = pthread_attr_init(&attr);
543   DCHECK_EQ(0, result);
544   // Native client uses default stack size.
545 #if !V8_OS_NACL
546   size_t stack_size = stack_size_;
547 #if V8_OS_AIX
548   if (stack_size == 0) {
549     // Default on AIX is 96KB -- bump up to 2MB
550     stack_size = 2 * 1024 * 1024;
551   }
552 #endif
553   if (stack_size > 0) {
554     result = pthread_attr_setstacksize(&attr, stack_size);
555     DCHECK_EQ(0, result);
556   }
557 #endif
558   {
559     LockGuard<Mutex> lock_guard(&data_->thread_creation_mutex_);
560     result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
561   }
562   DCHECK_EQ(0, result);
563   result = pthread_attr_destroy(&attr);
564   DCHECK_EQ(0, result);
565   DCHECK(data_->thread_ != kNoThread);
566   USE(result);
567 }
568
569
570 void Thread::Join() {
571   pthread_join(data_->thread_, NULL);
572 }
573
574
575 void Thread::YieldCPU() {
576   int result = sched_yield();
577   DCHECK_EQ(0, result);
578   USE(result);
579 }
580
581
582 static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
583 #if V8_OS_CYGWIN
584   // We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
585   // because pthread_key_t is a pointer type on Cygwin. This will probably not
586   // work on 64-bit platforms, but Cygwin doesn't support 64-bit anyway.
587   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
588   intptr_t ptr_key = reinterpret_cast<intptr_t>(pthread_key);
589   return static_cast<Thread::LocalStorageKey>(ptr_key);
590 #else
591   return static_cast<Thread::LocalStorageKey>(pthread_key);
592 #endif
593 }
594
595
596 static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) {
597 #if V8_OS_CYGWIN
598   STATIC_ASSERT(sizeof(Thread::LocalStorageKey) == sizeof(pthread_key_t));
599   intptr_t ptr_key = static_cast<intptr_t>(local_key);
600   return reinterpret_cast<pthread_key_t>(ptr_key);
601 #else
602   return static_cast<pthread_key_t>(local_key);
603 #endif
604 }
605
606
607 #ifdef V8_FAST_TLS_SUPPORTED
608
609 static Atomic32 tls_base_offset_initialized = 0;
610 intptr_t kMacTlsBaseOffset = 0;
611
612 // It's safe to do the initialization more that once, but it has to be
613 // done at least once.
614 static void InitializeTlsBaseOffset() {
615   const size_t kBufferSize = 128;
616   char buffer[kBufferSize];
617   size_t buffer_size = kBufferSize;
618   int ctl_name[] = { CTL_KERN , KERN_OSRELEASE };
619   if (sysctl(ctl_name, 2, buffer, &buffer_size, NULL, 0) != 0) {
620     V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version");
621   }
622   // The buffer now contains a string of the form XX.YY.ZZ, where
623   // XX is the major kernel version component.
624   // Make sure the buffer is 0-terminated.
625   buffer[kBufferSize - 1] = '\0';
626   char* period_pos = strchr(buffer, '.');
627   *period_pos = '\0';
628   int kernel_version_major =
629       static_cast<int>(strtol(buffer, NULL, 10));  // NOLINT
630   // The constants below are taken from pthreads.s from the XNU kernel
631   // sources archive at www.opensource.apple.com.
632   if (kernel_version_major < 11) {
633     // 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the
634     // same offsets.
635 #if V8_HOST_ARCH_IA32
636     kMacTlsBaseOffset = 0x48;
637 #else
638     kMacTlsBaseOffset = 0x60;
639 #endif
640   } else {
641     // 11.x.x (Lion) changed the offset.
642     kMacTlsBaseOffset = 0;
643   }
644
645   Release_Store(&tls_base_offset_initialized, 1);
646 }
647
648
649 static void CheckFastTls(Thread::LocalStorageKey key) {
650   void* expected = reinterpret_cast<void*>(0x1234CAFE);
651   Thread::SetThreadLocal(key, expected);
652   void* actual = Thread::GetExistingThreadLocal(key);
653   if (expected != actual) {
654     V8_Fatal(__FILE__, __LINE__,
655              "V8 failed to initialize fast TLS on current kernel");
656   }
657   Thread::SetThreadLocal(key, NULL);
658 }
659
660 #endif  // V8_FAST_TLS_SUPPORTED
661
662
663 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
664 #ifdef V8_FAST_TLS_SUPPORTED
665   bool check_fast_tls = false;
666   if (tls_base_offset_initialized == 0) {
667     check_fast_tls = true;
668     InitializeTlsBaseOffset();
669   }
670 #endif
671   pthread_key_t key;
672   int result = pthread_key_create(&key, NULL);
673   DCHECK_EQ(0, result);
674   USE(result);
675   LocalStorageKey local_key = PthreadKeyToLocalKey(key);
676 #ifdef V8_FAST_TLS_SUPPORTED
677   // If we just initialized fast TLS support, make sure it works.
678   if (check_fast_tls) CheckFastTls(local_key);
679 #endif
680   return local_key;
681 }
682
683
684 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
685   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
686   int result = pthread_key_delete(pthread_key);
687   DCHECK_EQ(0, result);
688   USE(result);
689 }
690
691
692 void* Thread::GetThreadLocal(LocalStorageKey key) {
693   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
694   return pthread_getspecific(pthread_key);
695 }
696
697
698 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
699   pthread_key_t pthread_key = LocalKeyToPthreadKey(key);
700   int result = pthread_setspecific(pthread_key, value);
701   DCHECK_EQ(0, result);
702   USE(result);
703 }
704
705
706 } }  // namespace v8::base