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 Linux 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/prctl.h> 35 #include <sys/time.h> 36 #include <sys/resource.h> 37 #include <sys/syscall.h> 38 #include <sys/types.h> 39 #include <stdlib.h> 40 41 // Ubuntu Dapper requires memory pages to be marked as 42 // executable. Otherwise, OS raises an exception when executing code 43 // in that page. 44 #include <sys/types.h> // mmap & munmap 45 #include <sys/mman.h> // mmap & munmap 46 #include <sys/stat.h> // open 47 #include <fcntl.h> // open 48 #include <unistd.h> // sysconf 49 #ifdef __GLIBC__ 50 #include <execinfo.h> // backtrace, backtrace_symbols 51 #endif // def __GLIBC__ 52 #include <strings.h> // index 53 #include <errno.h> 54 #include <stdarg.h> 55 56 #undef MAP_TYPE 57 58 #include "v8.h" 59 60 #include "platform-posix.h" 61 #include "platform.h" 62 #include "v8threads.h" 63 #include "vm-state-inl.h" 64 65 66 namespace v8 { 67 namespace internal { 68 69 // 0 is never a valid thread id on Linux since tids and pids share a 70 // name space and pid 0 is reserved (see man 2 kill). 71 static const pthread_t kNoThread = (pthread_t) 0; 72 73 74 double ceiling(double x) { 75 return ceil(x); 76 } 77 78 79 static Mutex* limit_mutex = NULL; 80 81 82 void OS::SetUp() { 83 // Seed the random number generator. We preserve microsecond resolution. 84 uint64_t seed = Ticks() ^ (getpid() << 16); 85 srandom(static_cast<unsigned int>(seed)); 86 limit_mutex = CreateMutex(); 87 88 #ifdef __arm__ 89 // When running on ARM hardware check that the EABI used by V8 and 90 // by the C code is the same. 91 bool hard_float = OS::ArmUsingHardFloat(); 92 if (hard_float) { 93 #if !USE_EABI_HARDFLOAT 94 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " 95 "-DUSE_EABI_HARDFLOAT\n"); 96 exit(1); 97 #endif 98 } else { 99 #if USE_EABI_HARDFLOAT 100 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " 101 "-DUSE_EABI_HARDFLOAT\n"); 102 exit(1); 103 #endif 104 } 105 #endif 106 } 107 108 109 void OS::PostSetUp() { 110 // Math functions depend on CPU features therefore they are initialized after 111 // CPU. 112 MathSetup(); 113 } 114 115 116 uint64_t OS::CpuFeaturesImpliedByPlatform() { 117 return 0; // Linux runs on anything. 118 } 119 120 121 #ifdef __arm__ 122 static bool CPUInfoContainsString(const char * search_string) { 123 const char* file_name = "/proc/cpuinfo"; 124 // This is written as a straight shot one pass parser 125 // and not using STL string and ifstream because, 126 // on Linux, it's reading from a (non-mmap-able) 127 // character special device. 128 FILE* f = NULL; 129 const char* what = search_string; 130 131 if (NULL == (f = fopen(file_name, "r"))) 132 return false; 133 134 int k; 135 while (EOF != (k = fgetc(f))) { 136 if (k == *what) { 137 ++what; 138 while ((*what != '\0') && (*what == fgetc(f))) { 139 ++what; 140 } 141 if (*what == '\0') { 142 fclose(f); 143 return true; 144 } else { 145 what = search_string; 146 } 147 } 148 } 149 fclose(f); 150 151 // Did not find string in the proc file. 152 return false; 153 } 154 155 156 bool OS::ArmCpuHasFeature(CpuFeature feature) { 157 const char* search_string = NULL; 158 // Simple detection of VFP at runtime for Linux. 159 // It is based on /proc/cpuinfo, which reveals hardware configuration 160 // to user-space applications. According to ARM (mid 2009), no similar 161 // facility is universally available on the ARM architectures, 162 // so it's up to individual OSes to provide such. 163 switch (feature) { 164 case VFP3: 165 search_string = "vfpv3"; 166 break; 167 case ARMv7: 168 search_string = "ARMv7"; 169 break; 170 default: 171 UNREACHABLE(); 172 } 173 174 if (CPUInfoContainsString(search_string)) { 175 return true; 176 } 177 178 if (feature == VFP3) { 179 // Some old kernels will report vfp not vfpv3. Here we make a last attempt 180 // to detect vfpv3 by checking for vfp *and* neon, since neon is only 181 // available on architectures with vfpv3. 182 // Checking neon on its own is not enough as it is possible to have neon 183 // without vfp. 184 if (CPUInfoContainsString("vfp") && CPUInfoContainsString("neon")) { 185 return true; 186 } 187 } 188 189 return false; 190 } 191 192 193 bool OS::ArmUsingHardFloat() { 194 // GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify 195 // the Floating Point ABI used (PCS stands for Procedure Call Standard). 196 // We use these as well as a couple of other defines to statically determine 197 // what FP ABI used. 198 // GCC versions 4.4 and below don't support hard-fp. 199 // GCC versions 4.5 may support hard-fp without defining __ARM_PCS or 200 // __ARM_PCS_VFP. 201 202 #define GCC_VERSION (__GNUC__ * 10000 \ 203 + __GNUC_MINOR__ * 100 \ 204 + __GNUC_PATCHLEVEL__) 205 #if GCC_VERSION >= 40600 206 #if defined(__ARM_PCS_VFP) 207 return true; 208 #else 209 return false; 210 #endif 211 212 #elif GCC_VERSION < 40500 213 return false; 214 215 #else 216 #if defined(__ARM_PCS_VFP) 217 return true; 218 #elif defined(__ARM_PCS) || defined(__SOFTFP) || !defined(__VFP_FP__) 219 return false; 220 #else 221 #error "Your version of GCC does not report the FP ABI compiled for." \ 222 "Please report it on this issue" \ 223 "http://code.google.com/p/v8/issues/detail?id=2140" 224 225 #endif 226 #endif 227 #undef GCC_VERSION 228 } 229 230 #endif // def __arm__ 231 232 233 #ifdef __mips__ 234 bool OS::MipsCpuHasFeature(CpuFeature feature) { 235 const char* search_string = NULL; 236 const char* file_name = "/proc/cpuinfo"; 237 // Simple detection of FPU at runtime for Linux. 238 // It is based on /proc/cpuinfo, which reveals hardware configuration 239 // to user-space applications. According to MIPS (early 2010), no similar 240 // facility is universally available on the MIPS architectures, 241 // so it's up to individual OSes to provide such. 242 // 243 // This is written as a straight shot one pass parser 244 // and not using STL string and ifstream because, 245 // on Linux, it's reading from a (non-mmap-able) 246 // character special device. 247 248 switch (feature) { 249 case FPU: 250 search_string = "FPU"; 251 break; 252 default: 253 UNREACHABLE(); 254 } 255 256 FILE* f = NULL; 257 const char* what = search_string; 258 259 if (NULL == (f = fopen(file_name, "r"))) 260 return false; 261 262 int k; 263 while (EOF != (k = fgetc(f))) { 264 if (k == *what) { 265 ++what; 266 while ((*what != '\0') && (*what == fgetc(f))) { 267 ++what; 268 } 269 if (*what == '\0') { 270 fclose(f); 271 return true; 272 } else { 273 what = search_string; 274 } 275 } 276 } 277 fclose(f); 278 279 // Did not find string in the proc file. 280 return false; 281 } 282 #endif // def __mips__ 283 284 285 int OS::ActivationFrameAlignment() { 286 #ifdef V8_TARGET_ARCH_ARM 287 // On EABI ARM targets this is required for fp correctness in the 288 // runtime system. 289 return 8; 290 #elif V8_TARGET_ARCH_MIPS 291 return 8; 292 #endif 293 // With gcc 4.4 the tree vectorization optimizer can generate code 294 // that requires 16 byte alignment such as movdqa on x86. 295 return 16; 296 } 297 298 299 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 300 #if (defined(V8_TARGET_ARCH_ARM) && defined(__arm__)) || \ 301 (defined(V8_TARGET_ARCH_MIPS) && defined(__mips__)) 302 // Only use on ARM or MIPS hardware. 303 MemoryBarrier(); 304 #else 305 __asm__ __volatile__("" : : : "memory"); 306 // An x86 store acts as a release barrier. 307 #endif 308 *ptr = value; 309 } 310 311 312 const char* OS::LocalTimezone(double time) { 313 if (isnan(time)) return ""; 314 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 315 struct tm* t = localtime(&tv); 316 if (NULL == t) return ""; 317 return t->tm_zone; 318 } 319 320 321 double OS::LocalTimeOffset() { 322 time_t tv = time(NULL); 323 struct tm* t = localtime(&tv); 324 // tm_gmtoff includes any daylight savings offset, so subtract it. 325 return static_cast<double>(t->tm_gmtoff * msPerSecond - 326 (t->tm_isdst > 0 ? 3600 * msPerSecond : 0)); 327 } 328 329 330 // We keep the lowest and highest addresses mapped as a quick way of 331 // determining that pointers are outside the heap (used mostly in assertions 332 // and verification). The estimate is conservative, i.e., not all addresses in 333 // 'allocated' space are actually allocated to our heap. The range is 334 // [lowest, highest), inclusive on the low and and exclusive on the high end. 335 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 336 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 337 338 339 static void UpdateAllocatedSpaceLimits(void* address, int size) { 340 ASSERT(limit_mutex != NULL); 341 ScopedLock lock(limit_mutex); 342 343 lowest_ever_allocated = Min(lowest_ever_allocated, address); 344 highest_ever_allocated = 345 Max(highest_ever_allocated, 346 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 347 } 348 349 350 bool OS::IsOutsideAllocatedSpace(void* address) { 351 return address < lowest_ever_allocated || address >= highest_ever_allocated; 352 } 353 354 355 size_t OS::AllocateAlignment() { 356 return sysconf(_SC_PAGESIZE); 357 } 358 359 360 void* OS::Allocate(const size_t requested, 361 size_t* allocated, 362 bool is_executable) { 363 const size_t msize = RoundUp(requested, AllocateAlignment()); 364 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 365 void* addr = OS::GetRandomMmapAddr(); 366 void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 367 if (mbase == MAP_FAILED) { 368 LOG(i::Isolate::Current(), 369 StringEvent("OS::Allocate", "mmap failed")); 370 return NULL; 371 } 372 *allocated = msize; 373 UpdateAllocatedSpaceLimits(mbase, msize); 374 return mbase; 375 } 376 377 378 void OS::Free(void* address, const size_t size) { 379 // TODO(1240712): munmap has a return value which is ignored here. 380 int result = munmap(address, size); 381 USE(result); 382 ASSERT(result == 0); 383 } 384 385 386 void OS::Sleep(int milliseconds) { 387 unsigned int ms = static_cast<unsigned int>(milliseconds); 388 usleep(1000 * ms); 389 } 390 391 392 void OS::Abort() { 393 // Redirect to std abort to signal abnormal program termination. 394 if (FLAG_break_on_abort) { 395 DebugBreak(); 396 } 397 abort(); 398 } 399 400 401 void OS::DebugBreak() { 402 // TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x, 403 // which is the architecture of generated code). 404 #if (defined(__arm__) || defined(__thumb__)) 405 # if defined(CAN_USE_ARMV5_INSTRUCTIONS) 406 asm("bkpt 0"); 407 # endif 408 #elif defined(__mips__) 409 asm("break"); 410 #else 411 asm("int $3"); 412 #endif 413 } 414 415 416 class PosixMemoryMappedFile : public OS::MemoryMappedFile { 417 public: 418 PosixMemoryMappedFile(FILE* file, void* memory, int size) 419 : file_(file), memory_(memory), size_(size) { } 420 virtual ~PosixMemoryMappedFile(); 421 virtual void* memory() { return memory_; } 422 virtual int size() { return size_; } 423 private: 424 FILE* file_; 425 void* memory_; 426 int size_; 427 }; 428 429 430 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 431 FILE* file = fopen(name, "r+"); 432 if (file == NULL) return NULL; 433 434 fseek(file, 0, SEEK_END); 435 int size = ftell(file); 436 437 void* memory = 438 mmap(OS::GetRandomMmapAddr(), 439 size, 440 PROT_READ | PROT_WRITE, 441 MAP_SHARED, 442 fileno(file), 443 0); 444 return new PosixMemoryMappedFile(file, memory, size); 445 } 446 447 448 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 449 void* initial) { 450 FILE* file = fopen(name, "w+"); 451 if (file == NULL) return NULL; 452 int result = fwrite(initial, size, 1, file); 453 if (result < 1) { 454 fclose(file); 455 return NULL; 456 } 457 void* memory = 458 mmap(OS::GetRandomMmapAddr(), 459 size, 460 PROT_READ | PROT_WRITE, 461 MAP_SHARED, 462 fileno(file), 463 0); 464 return new PosixMemoryMappedFile(file, memory, size); 465 } 466 467 468 PosixMemoryMappedFile::~PosixMemoryMappedFile() { 469 if (memory_) OS::Free(memory_, size_); 470 fclose(file_); 471 } 472 473 474 void OS::LogSharedLibraryAddresses() { 475 // This function assumes that the layout of the file is as follows: 476 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 477 // If we encounter an unexpected situation we abort scanning further entries. 478 FILE* fp = fopen("/proc/self/maps", "r"); 479 if (fp == NULL) return; 480 481 // Allocate enough room to be able to store a full file name. 482 const int kLibNameLen = FILENAME_MAX + 1; 483 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 484 485 i::Isolate* isolate = ISOLATE; 486 // This loop will terminate once the scanning hits an EOF. 487 while (true) { 488 uintptr_t start, end; 489 char attr_r, attr_w, attr_x, attr_p; 490 // Parse the addresses and permission bits at the beginning of the line. 491 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 492 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 493 494 int c; 495 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 496 // Found a read-only executable entry. Skip characters until we reach 497 // the beginning of the filename or the end of the line. 498 do { 499 c = getc(fp); 500 } while ((c != EOF) && (c != '\n') && (c != '/')); 501 if (c == EOF) break; // EOF: Was unexpected, just exit. 502 503 // Process the filename if found. 504 if (c == '/') { 505 ungetc(c, fp); // Push the '/' back into the stream to be read below. 506 507 // Read to the end of the line. Exit if the read fails. 508 if (fgets(lib_name, kLibNameLen, fp) == NULL) break; 509 510 // Drop the newline character read by fgets. We do not need to check 511 // for a zero-length string because we know that we at least read the 512 // '/' character. 513 lib_name[strlen(lib_name) - 1] = '\0'; 514 } else { 515 // No library name found, just record the raw address range. 516 snprintf(lib_name, kLibNameLen, 517 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 518 } 519 LOG(isolate, SharedLibraryEvent(lib_name, start, end)); 520 } else { 521 // Entry not describing executable data. Skip to end of line to set up 522 // reading the next entry. 523 do { 524 c = getc(fp); 525 } while ((c != EOF) && (c != '\n')); 526 if (c == EOF) break; 527 } 528 } 529 free(lib_name); 530 fclose(fp); 531 } 532 533 534 static const char kGCFakeMmap[] = "/tmp/__v8_gc__"; 535 536 537 void OS::SignalCodeMovingGC() { 538 // Support for ll_prof.py. 539 // 540 // The Linux profiler built into the kernel logs all mmap's with 541 // PROT_EXEC so that analysis tools can properly attribute ticks. We 542 // do a mmap with a name known by ll_prof.py and immediately munmap 543 // it. This injects a GC marker into the stream of events generated 544 // by the kernel and allows us to synchronize V8 code log and the 545 // kernel log. 546 int size = sysconf(_SC_PAGESIZE); 547 FILE* f = fopen(kGCFakeMmap, "w+"); 548 void* addr = mmap(OS::GetRandomMmapAddr(), 549 size, 550 PROT_READ | PROT_EXEC, 551 MAP_PRIVATE, 552 fileno(f), 553 0); 554 ASSERT(addr != MAP_FAILED); 555 OS::Free(addr, size); 556 fclose(f); 557 } 558 559 560 int OS::StackWalk(Vector<OS::StackFrame> frames) { 561 // backtrace is a glibc extension. 562 #ifdef __GLIBC__ 563 int frames_size = frames.length(); 564 ScopedVector<void*> addresses(frames_size); 565 566 int frames_count = backtrace(addresses.start(), frames_size); 567 568 char** symbols = backtrace_symbols(addresses.start(), frames_count); 569 if (symbols == NULL) { 570 return kStackWalkError; 571 } 572 573 for (int i = 0; i < frames_count; i++) { 574 frames[i].address = addresses[i]; 575 // Format a text representation of the frame based on the information 576 // available. 577 SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen), 578 "%s", 579 symbols[i]); 580 // Make sure line termination is in place. 581 frames[i].text[kStackWalkMaxTextLen - 1] = '\0'; 582 } 583 584 free(symbols); 585 586 return frames_count; 587 #else // ndef __GLIBC__ 588 return 0; 589 #endif // ndef __GLIBC__ 590 } 591 592 593 // Constants used for mmap. 594 static const int kMmapFd = -1; 595 static const int kMmapFdOffset = 0; 596 597 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 598 599 VirtualMemory::VirtualMemory(size_t size) { 600 address_ = ReserveRegion(size); 601 size_ = size; 602 } 603 604 605 VirtualMemory::VirtualMemory(size_t size, size_t alignment) 606 : address_(NULL), size_(0) { 607 ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 608 size_t request_size = RoundUp(size + alignment, 609 static_cast<intptr_t>(OS::AllocateAlignment())); 610 void* reservation = mmap(OS::GetRandomMmapAddr(), 611 request_size, 612 PROT_NONE, 613 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 614 kMmapFd, 615 kMmapFdOffset); 616 if (reservation == MAP_FAILED) return; 617 618 Address base = static_cast<Address>(reservation); 619 Address aligned_base = RoundUp(base, alignment); 620 ASSERT_LE(base, aligned_base); 621 622 // Unmap extra memory reserved before and after the desired block. 623 if (aligned_base != base) { 624 size_t prefix_size = static_cast<size_t>(aligned_base - base); 625 OS::Free(base, prefix_size); 626 request_size -= prefix_size; 627 } 628 629 size_t aligned_size = RoundUp(size, OS::AllocateAlignment()); 630 ASSERT_LE(aligned_size, request_size); 631 632 if (aligned_size != request_size) { 633 size_t suffix_size = request_size - aligned_size; 634 OS::Free(aligned_base + aligned_size, suffix_size); 635 request_size -= suffix_size; 636 } 637 638 ASSERT(aligned_size == request_size); 639 640 address_ = static_cast<void*>(aligned_base); 641 size_ = aligned_size; 642 } 643 644 645 VirtualMemory::~VirtualMemory() { 646 if (IsReserved()) { 647 bool result = ReleaseRegion(address(), size()); 648 ASSERT(result); 649 USE(result); 650 } 651 } 652 653 654 bool VirtualMemory::IsReserved() { 655 return address_ != NULL; 656 } 657 658 659 void VirtualMemory::Reset() { 660 address_ = NULL; 661 size_ = 0; 662 } 663 664 665 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 666 return CommitRegion(address, size, is_executable); 667 } 668 669 670 bool VirtualMemory::Uncommit(void* address, size_t size) { 671 return UncommitRegion(address, size); 672 } 673 674 675 bool VirtualMemory::Guard(void* address) { 676 OS::Guard(address, OS::CommitPageSize()); 677 return true; 678 } 679 680 681 void* VirtualMemory::ReserveRegion(size_t size) { 682 void* result = mmap(OS::GetRandomMmapAddr(), 683 size, 684 PROT_NONE, 685 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, 686 kMmapFd, 687 kMmapFdOffset); 688 689 if (result == MAP_FAILED) return NULL; 690 691 return result; 692 } 693 694 695 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 696 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 697 if (MAP_FAILED == mmap(base, 698 size, 699 prot, 700 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 701 kMmapFd, 702 kMmapFdOffset)) { 703 return false; 704 } 705 706 UpdateAllocatedSpaceLimits(base, size); 707 return true; 708 } 709 710 711 bool VirtualMemory::UncommitRegion(void* base, size_t size) { 712 return mmap(base, 713 size, 714 PROT_NONE, 715 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, 716 kMmapFd, 717 kMmapFdOffset) != MAP_FAILED; 718 } 719 720 721 bool VirtualMemory::ReleaseRegion(void* base, size_t size) { 722 return munmap(base, size) == 0; 723 } 724 725 726 class Thread::PlatformData : public Malloced { 727 public: 728 PlatformData() : thread_(kNoThread) {} 729 730 pthread_t thread_; // Thread handle for pthread. 731 }; 732 733 Thread::Thread(const Options& options) 734 : data_(new PlatformData()), 735 stack_size_(options.stack_size()) { 736 set_name(options.name()); 737 } 738 739 740 Thread::~Thread() { 741 delete data_; 742 } 743 744 745 static void* ThreadEntry(void* arg) { 746 Thread* thread = reinterpret_cast<Thread*>(arg); 747 // This is also initialized by the first argument to pthread_create() but we 748 // don't know which thread will run first (the original thread or the new 749 // one) so we initialize it here too. 750 #ifdef PR_SET_NAME 751 prctl(PR_SET_NAME, 752 reinterpret_cast<unsigned long>(thread->name()), // NOLINT 753 0, 0, 0); 754 #endif 755 thread->data()->thread_ = pthread_self(); 756 ASSERT(thread->data()->thread_ != kNoThread); 757 thread->Run(); 758 return NULL; 759 } 760 761 762 void Thread::set_name(const char* name) { 763 strncpy(name_, name, sizeof(name_)); 764 name_[sizeof(name_) - 1] = '\0'; 765 } 766 767 768 void Thread::Start() { 769 pthread_attr_t* attr_ptr = NULL; 770 pthread_attr_t attr; 771 if (stack_size_ > 0) { 772 pthread_attr_init(&attr); 773 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 774 attr_ptr = &attr; 775 } 776 int result = pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 777 CHECK_EQ(0, result); 778 ASSERT(data_->thread_ != kNoThread); 779 } 780 781 782 void Thread::Join() { 783 pthread_join(data_->thread_, NULL); 784 } 785 786 787 Thread::LocalStorageKey Thread::CreateThreadLocalKey() { 788 pthread_key_t key; 789 int result = pthread_key_create(&key, NULL); 790 USE(result); 791 ASSERT(result == 0); 792 return static_cast<LocalStorageKey>(key); 793 } 794 795 796 void Thread::DeleteThreadLocalKey(LocalStorageKey key) { 797 pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 798 int result = pthread_key_delete(pthread_key); 799 USE(result); 800 ASSERT(result == 0); 801 } 802 803 804 void* Thread::GetThreadLocal(LocalStorageKey key) { 805 pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 806 return pthread_getspecific(pthread_key); 807 } 808 809 810 void Thread::SetThreadLocal(LocalStorageKey key, void* value) { 811 pthread_key_t pthread_key = static_cast<pthread_key_t>(key); 812 pthread_setspecific(pthread_key, value); 813 } 814 815 816 void Thread::YieldCPU() { 817 sched_yield(); 818 } 819 820 821 class LinuxMutex : public Mutex { 822 public: 823 LinuxMutex() { 824 pthread_mutexattr_t attrs; 825 int result = pthread_mutexattr_init(&attrs); 826 ASSERT(result == 0); 827 result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE); 828 ASSERT(result == 0); 829 result = pthread_mutex_init(&mutex_, &attrs); 830 ASSERT(result == 0); 831 USE(result); 832 } 833 834 virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); } 835 836 virtual int Lock() { 837 int result = pthread_mutex_lock(&mutex_); 838 return result; 839 } 840 841 virtual int Unlock() { 842 int result = pthread_mutex_unlock(&mutex_); 843 return result; 844 } 845 846 virtual bool TryLock() { 847 int result = pthread_mutex_trylock(&mutex_); 848 // Return false if the lock is busy and locking failed. 849 if (result == EBUSY) { 850 return false; 851 } 852 ASSERT(result == 0); // Verify no other errors. 853 return true; 854 } 855 856 private: 857 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 858 }; 859 860 861 Mutex* OS::CreateMutex() { 862 return new LinuxMutex(); 863 } 864 865 866 class LinuxSemaphore : public Semaphore { 867 public: 868 explicit LinuxSemaphore(int count) { sem_init(&sem_, 0, count); } 869 virtual ~LinuxSemaphore() { sem_destroy(&sem_); } 870 871 virtual void Wait(); 872 virtual bool Wait(int timeout); 873 virtual void Signal() { sem_post(&sem_); } 874 private: 875 sem_t sem_; 876 }; 877 878 879 void LinuxSemaphore::Wait() { 880 while (true) { 881 int result = sem_wait(&sem_); 882 if (result == 0) return; // Successfully got semaphore. 883 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 884 } 885 } 886 887 888 #ifndef TIMEVAL_TO_TIMESPEC 889 #define TIMEVAL_TO_TIMESPEC(tv, ts) do { \ 890 (ts)->tv_sec = (tv)->tv_sec; \ 891 (ts)->tv_nsec = (tv)->tv_usec * 1000; \ 892 } while (false) 893 #endif 894 895 896 bool LinuxSemaphore::Wait(int timeout) { 897 const long kOneSecondMicros = 1000000; // NOLINT 898 899 // Split timeout into second and nanosecond parts. 900 struct timeval delta; 901 delta.tv_usec = timeout % kOneSecondMicros; 902 delta.tv_sec = timeout / kOneSecondMicros; 903 904 struct timeval current_time; 905 // Get the current time. 906 if (gettimeofday(¤t_time, NULL) == -1) { 907 return false; 908 } 909 910 // Calculate time for end of timeout. 911 struct timeval end_time; 912 timeradd(¤t_time, &delta, &end_time); 913 914 struct timespec ts; 915 TIMEVAL_TO_TIMESPEC(&end_time, &ts); 916 // Wait for semaphore signalled or timeout. 917 while (true) { 918 int result = sem_timedwait(&sem_, &ts); 919 if (result == 0) return true; // Successfully got semaphore. 920 if (result > 0) { 921 // For glibc prior to 2.3.4 sem_timedwait returns the error instead of -1. 922 errno = result; 923 result = -1; 924 } 925 if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 926 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 927 } 928 } 929 930 931 Semaphore* OS::CreateSemaphore(int count) { 932 return new LinuxSemaphore(count); 933 } 934 935 936 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) 937 // Android runs a fairly new Linux kernel, so signal info is there, 938 // but the C library doesn't have the structs defined. 939 940 struct sigcontext { 941 uint32_t trap_no; 942 uint32_t error_code; 943 uint32_t oldmask; 944 uint32_t gregs[16]; 945 uint32_t arm_cpsr; 946 uint32_t fault_address; 947 }; 948 typedef uint32_t __sigset_t; 949 typedef struct sigcontext mcontext_t; 950 typedef struct ucontext { 951 uint32_t uc_flags; 952 struct ucontext* uc_link; 953 stack_t uc_stack; 954 mcontext_t uc_mcontext; 955 __sigset_t uc_sigmask; 956 } ucontext_t; 957 enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11}; 958 959 #elif !defined(__GLIBC__) && defined(__mips__) 960 // MIPS version of sigcontext, for Android bionic. 961 struct sigcontext { 962 uint32_t regmask; 963 uint32_t status; 964 uint64_t pc; 965 uint64_t gregs[32]; 966 uint64_t fpregs[32]; 967 uint32_t acx; 968 uint32_t fpc_csr; 969 uint32_t fpc_eir; 970 uint32_t used_math; 971 uint32_t dsp; 972 uint64_t mdhi; 973 uint64_t mdlo; 974 uint32_t hi1; 975 uint32_t lo1; 976 uint32_t hi2; 977 uint32_t lo2; 978 uint32_t hi3; 979 uint32_t lo3; 980 }; 981 typedef uint32_t __sigset_t; 982 typedef struct sigcontext mcontext_t; 983 typedef struct ucontext { 984 uint32_t uc_flags; 985 struct ucontext* uc_link; 986 stack_t uc_stack; 987 mcontext_t uc_mcontext; 988 __sigset_t uc_sigmask; 989 } ucontext_t; 990 991 #elif !defined(__GLIBC__) && defined(__i386__) 992 // x86 version for Android. 993 struct sigcontext { 994 uint32_t gregs[19]; 995 void* fpregs; 996 uint32_t oldmask; 997 uint32_t cr2; 998 }; 999 1000 typedef uint32_t __sigset_t; 1001 typedef struct sigcontext mcontext_t; 1002 typedef struct ucontext { 1003 uint32_t uc_flags; 1004 struct ucontext* uc_link; 1005 stack_t uc_stack; 1006 mcontext_t uc_mcontext; 1007 __sigset_t uc_sigmask; 1008 } ucontext_t; 1009 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; 1010 #endif 1011 1012 1013 static int GetThreadID() { 1014 // Glibc doesn't provide a wrapper for gettid(2). 1015 #if defined(ANDROID) 1016 return syscall(__NR_gettid); 1017 #else 1018 return syscall(SYS_gettid); 1019 #endif 1020 } 1021 1022 1023 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 1024 USE(info); 1025 if (signal != SIGPROF) return; 1026 Isolate* isolate = Isolate::UncheckedCurrent(); 1027 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) { 1028 // We require a fully initialized and entered isolate. 1029 return; 1030 } 1031 if (v8::Locker::IsActive() && 1032 !isolate->thread_manager()->IsLockedByCurrentThread()) { 1033 return; 1034 } 1035 1036 Sampler* sampler = isolate->logger()->sampler(); 1037 if (sampler == NULL || !sampler->IsActive()) return; 1038 1039 TickSample sample_obj; 1040 TickSample* sample = CpuProfiler::TickSampleEvent(isolate); 1041 if (sample == NULL) sample = &sample_obj; 1042 1043 // Extracting the sample from the context is extremely machine dependent. 1044 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 1045 mcontext_t& mcontext = ucontext->uc_mcontext; 1046 sample->state = isolate->current_vm_state(); 1047 #if V8_HOST_ARCH_IA32 1048 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 1049 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 1050 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); 1051 #elif V8_HOST_ARCH_X64 1052 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); 1053 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); 1054 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); 1055 #elif V8_HOST_ARCH_ARM 1056 // An undefined macro evaluates to 0, so this applies to Android's Bionic also. 1057 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) 1058 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); 1059 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); 1060 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); 1061 #else 1062 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); 1063 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); 1064 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); 1065 #endif // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) 1066 #elif V8_HOST_ARCH_MIPS 1067 sample->pc = reinterpret_cast<Address>(mcontext.pc); 1068 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); 1069 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); 1070 #endif // V8_HOST_ARCH_* 1071 sampler->SampleStack(sample); 1072 sampler->Tick(sample); 1073 } 1074 1075 1076 class Sampler::PlatformData : public Malloced { 1077 public: 1078 PlatformData() : vm_tid_(GetThreadID()) {} 1079 1080 int vm_tid() const { return vm_tid_; } 1081 1082 private: 1083 const int vm_tid_; 1084 }; 1085 1086 1087 class SignalSender : public Thread { 1088 public: 1089 enum SleepInterval { 1090 HALF_INTERVAL, 1091 FULL_INTERVAL 1092 }; 1093 1094 static const int kSignalSenderStackSize = 64 * KB; 1095 1096 explicit SignalSender(int interval) 1097 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), 1098 vm_tgid_(getpid()), 1099 interval_(interval) {} 1100 1101 static void InstallSignalHandler() { 1102 struct sigaction sa; 1103 sa.sa_sigaction = ProfilerSignalHandler; 1104 sigemptyset(&sa.sa_mask); 1105 sa.sa_flags = SA_RESTART | SA_SIGINFO; 1106 signal_handler_installed_ = 1107 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 1108 } 1109 1110 static void RestoreSignalHandler() { 1111 if (signal_handler_installed_) { 1112 sigaction(SIGPROF, &old_signal_handler_, 0); 1113 signal_handler_installed_ = false; 1114 } 1115 } 1116 1117 static void AddActiveSampler(Sampler* sampler) { 1118 ScopedLock lock(mutex_.Pointer()); 1119 SamplerRegistry::AddActiveSampler(sampler); 1120 if (instance_ == NULL) { 1121 // Start a thread that will send SIGPROF signal to VM threads, 1122 // when CPU profiling will be enabled. 1123 instance_ = new SignalSender(sampler->interval()); 1124 instance_->Start(); 1125 } else { 1126 ASSERT(instance_->interval_ == sampler->interval()); 1127 } 1128 } 1129 1130 static void RemoveActiveSampler(Sampler* sampler) { 1131 ScopedLock lock(mutex_.Pointer()); 1132 SamplerRegistry::RemoveActiveSampler(sampler); 1133 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 1134 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 1135 delete instance_; 1136 instance_ = NULL; 1137 RestoreSignalHandler(); 1138 } 1139 } 1140 1141 // Implement Thread::Run(). 1142 virtual void Run() { 1143 SamplerRegistry::State state; 1144 while ((state = SamplerRegistry::GetState()) != 1145 SamplerRegistry::HAS_NO_SAMPLERS) { 1146 bool cpu_profiling_enabled = 1147 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 1148 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 1149 if (cpu_profiling_enabled && !signal_handler_installed_) { 1150 InstallSignalHandler(); 1151 } else if (!cpu_profiling_enabled && signal_handler_installed_) { 1152 RestoreSignalHandler(); 1153 } 1154 // When CPU profiling is enabled both JavaScript and C++ code is 1155 // profiled. We must not suspend. 1156 if (!cpu_profiling_enabled) { 1157 if (rate_limiter_.SuspendIfNecessary()) continue; 1158 } 1159 if (cpu_profiling_enabled && runtime_profiler_enabled) { 1160 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 1161 return; 1162 } 1163 Sleep(HALF_INTERVAL); 1164 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 1165 return; 1166 } 1167 Sleep(HALF_INTERVAL); 1168 } else { 1169 if (cpu_profiling_enabled) { 1170 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, 1171 this)) { 1172 return; 1173 } 1174 } 1175 if (runtime_profiler_enabled) { 1176 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, 1177 NULL)) { 1178 return; 1179 } 1180 } 1181 Sleep(FULL_INTERVAL); 1182 } 1183 } 1184 } 1185 1186 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 1187 if (!sampler->IsProfiling()) return; 1188 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 1189 sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); 1190 } 1191 1192 static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 1193 if (!sampler->isolate()->IsInitialized()) return; 1194 sampler->isolate()->runtime_profiler()->NotifyTick(); 1195 } 1196 1197 void SendProfilingSignal(int tid) { 1198 if (!signal_handler_installed_) return; 1199 // Glibc doesn't provide a wrapper for tgkill(2). 1200 #if defined(ANDROID) 1201 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF); 1202 #else 1203 syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF); 1204 #endif 1205 } 1206 1207 void Sleep(SleepInterval full_or_half) { 1208 // Convert ms to us and subtract 100 us to compensate delays 1209 // occuring during signal delivery. 1210 useconds_t interval = interval_ * 1000 - 100; 1211 if (full_or_half == HALF_INTERVAL) interval /= 2; 1212 #if defined(ANDROID) 1213 usleep(interval); 1214 #else 1215 int result = usleep(interval); 1216 #ifdef DEBUG 1217 if (result != 0 && errno != EINTR) { 1218 fprintf(stderr, 1219 "SignalSender usleep error; interval = %u, errno = %d\n", 1220 interval, 1221 errno); 1222 ASSERT(result == 0 || errno == EINTR); 1223 } 1224 #endif // DEBUG 1225 USE(result); 1226 #endif // ANDROID 1227 } 1228 1229 const int vm_tgid_; 1230 const int interval_; 1231 RuntimeProfilerRateLimiter rate_limiter_; 1232 1233 // Protects the process wide state below. 1234 static LazyMutex mutex_; 1235 static SignalSender* instance_; 1236 static bool signal_handler_installed_; 1237 static struct sigaction old_signal_handler_; 1238 1239 private: 1240 DISALLOW_COPY_AND_ASSIGN(SignalSender); 1241 }; 1242 1243 1244 LazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; 1245 SignalSender* SignalSender::instance_ = NULL; 1246 struct sigaction SignalSender::old_signal_handler_; 1247 bool SignalSender::signal_handler_installed_ = false; 1248 1249 1250 Sampler::Sampler(Isolate* isolate, int interval) 1251 : isolate_(isolate), 1252 interval_(interval), 1253 profiling_(false), 1254 active_(false), 1255 samples_taken_(0) { 1256 data_ = new PlatformData; 1257 } 1258 1259 1260 Sampler::~Sampler() { 1261 ASSERT(!IsActive()); 1262 delete data_; 1263 } 1264 1265 1266 void Sampler::Start() { 1267 ASSERT(!IsActive()); 1268 SetActive(true); 1269 SignalSender::AddActiveSampler(this); 1270 } 1271 1272 1273 void Sampler::Stop() { 1274 ASSERT(IsActive()); 1275 SignalSender::RemoveActiveSampler(this); 1276 SetActive(false); 1277 } 1278 1279 1280 } } // namespace v8::internal 1281