OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 | 69 |
70 #include "platform-posix.h" | 70 #include "platform-posix.h" |
71 #include "platform.h" | 71 #include "platform.h" |
72 #include "v8threads.h" | 72 #include "v8threads.h" |
73 #include "vm-state-inl.h" | 73 #include "vm-state-inl.h" |
74 | 74 |
75 | 75 |
76 namespace v8 { | 76 namespace v8 { |
77 namespace internal { | 77 namespace internal { |
78 | 78 |
79 // 0 is never a valid thread id on Linux since tids and pids share a | |
80 // name space and pid 0 is reserved (see man 2 kill). | |
81 static const pthread_t kNoThread = (pthread_t) 0; | |
82 | |
83 | |
84 double ceiling(double x) { | |
85 return ceil(x); | |
86 } | |
87 | |
88 | 79 |
89 static Mutex* limit_mutex = NULL; | 80 static Mutex* limit_mutex = NULL; |
90 | 81 |
91 | 82 |
92 void OS::PostSetUp() { | |
93 POSIXPostSetUp(); | |
94 } | |
95 | |
96 | |
97 uint64_t OS::CpuFeaturesImpliedByPlatform() { | |
98 return 0; // Linux runs on anything. | |
99 } | |
100 | |
101 | |
102 #ifdef __arm__ | 83 #ifdef __arm__ |
103 static bool CPUInfoContainsString(const char * search_string) { | 84 static bool CPUInfoContainsString(const char * search_string) { |
104 const char* file_name = "/proc/cpuinfo"; | 85 const char* file_name = "/proc/cpuinfo"; |
105 // This is written as a straight shot one pass parser | 86 // This is written as a straight shot one pass parser |
106 // and not using STL string and ifstream because, | 87 // and not using STL string and ifstream because, |
107 // on Linux, it's reading from a (non-mmap-able) | 88 // on Linux, it's reading from a (non-mmap-able) |
108 // character special device. | 89 // character special device. |
109 FILE* f = NULL; | 90 FILE* f = NULL; |
110 const char* what = search_string; | 91 const char* what = search_string; |
111 | 92 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 } | 302 } |
322 } | 303 } |
323 fclose(f); | 304 fclose(f); |
324 | 305 |
325 // Did not find string in the proc file. | 306 // Did not find string in the proc file. |
326 return false; | 307 return false; |
327 } | 308 } |
328 #endif // def __mips__ | 309 #endif // def __mips__ |
329 | 310 |
330 | 311 |
331 int OS::ActivationFrameAlignment() { | |
332 #if V8_TARGET_ARCH_ARM | |
333 // On EABI ARM targets this is required for fp correctness in the | |
334 // runtime system. | |
335 return 8; | |
336 #elif V8_TARGET_ARCH_MIPS | |
337 return 8; | |
338 #endif | |
339 // With gcc 4.4 the tree vectorization optimizer can generate code | |
340 // that requires 16 byte alignment such as movdqa on x86. | |
341 return 16; | |
342 } | |
343 | |
344 | |
345 const char* OS::LocalTimezone(double time) { | 312 const char* OS::LocalTimezone(double time) { |
346 if (std::isnan(time)) return ""; | 313 if (std::isnan(time)) return ""; |
347 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); | 314 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); |
348 struct tm* t = localtime(&tv); | 315 struct tm* t = localtime(&tv); |
349 if (NULL == t) return ""; | 316 if (NULL == t) return ""; |
350 return t->tm_zone; | 317 return t->tm_zone; |
351 } | 318 } |
352 | 319 |
353 | 320 |
354 double OS::LocalTimeOffset() { | 321 double OS::LocalTimeOffset() { |
(...skipping 23 matching lines...) Expand all Loading... |
378 Max(highest_ever_allocated, | 345 Max(highest_ever_allocated, |
379 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); | 346 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); |
380 } | 347 } |
381 | 348 |
382 | 349 |
383 bool OS::IsOutsideAllocatedSpace(void* address) { | 350 bool OS::IsOutsideAllocatedSpace(void* address) { |
384 return address < lowest_ever_allocated || address >= highest_ever_allocated; | 351 return address < lowest_ever_allocated || address >= highest_ever_allocated; |
385 } | 352 } |
386 | 353 |
387 | 354 |
388 size_t OS::AllocateAlignment() { | |
389 return sysconf(_SC_PAGESIZE); | |
390 } | |
391 | |
392 | |
393 void* OS::Allocate(const size_t requested, | 355 void* OS::Allocate(const size_t requested, |
394 size_t* allocated, | 356 size_t* allocated, |
395 bool is_executable) { | 357 bool is_executable) { |
396 const size_t msize = RoundUp(requested, AllocateAlignment()); | 358 const size_t msize = RoundUp(requested, AllocateAlignment()); |
397 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); | 359 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); |
398 void* addr = OS::GetRandomMmapAddr(); | 360 void* addr = OS::GetRandomMmapAddr(); |
399 void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 361 void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
400 if (mbase == MAP_FAILED) { | 362 if (mbase == MAP_FAILED) { |
401 LOG(i::Isolate::Current(), | 363 LOG(i::Isolate::Current(), |
402 StringEvent("OS::Allocate", "mmap failed")); | 364 StringEvent("OS::Allocate", "mmap failed")); |
403 return NULL; | 365 return NULL; |
404 } | 366 } |
405 *allocated = msize; | 367 *allocated = msize; |
406 UpdateAllocatedSpaceLimits(mbase, msize); | 368 UpdateAllocatedSpaceLimits(mbase, msize); |
407 return mbase; | 369 return mbase; |
408 } | 370 } |
409 | 371 |
410 | 372 |
411 void OS::Free(void* address, const size_t size) { | |
412 // TODO(1240712): munmap has a return value which is ignored here. | |
413 int result = munmap(address, size); | |
414 USE(result); | |
415 ASSERT(result == 0); | |
416 } | |
417 | |
418 | |
419 void OS::Sleep(int milliseconds) { | |
420 unsigned int ms = static_cast<unsigned int>(milliseconds); | |
421 usleep(1000 * ms); | |
422 } | |
423 | |
424 | |
425 int OS::NumberOfCores() { | |
426 return sysconf(_SC_NPROCESSORS_ONLN); | |
427 } | |
428 | |
429 | |
430 void OS::Abort() { | |
431 // Redirect to std abort to signal abnormal program termination. | |
432 if (FLAG_break_on_abort) { | |
433 DebugBreak(); | |
434 } | |
435 abort(); | |
436 } | |
437 | |
438 | |
439 void OS::DebugBreak() { | |
440 // TODO(lrn): Introduce processor define for runtime system (!= V8_ARCH_x, | |
441 // which is the architecture of generated code). | |
442 #if defined(__arm__) || defined(__thumb__) | |
443 asm("bkpt 0"); | |
444 #elif defined(__aarch64__) | |
445 asm("brk 0"); | |
446 #elif defined(__mips__) | |
447 asm("break"); | |
448 #elif defined(__native_client__) | |
449 asm("hlt"); | |
450 #else | |
451 asm("int $3"); | |
452 #endif | |
453 } | |
454 | |
455 | |
456 void OS::DumpBacktrace() { | 373 void OS::DumpBacktrace() { |
457 // backtrace is a glibc extension. | 374 // backtrace is a glibc extension. |
458 #if defined(__GLIBC__) && !defined(__UCLIBC__) | 375 #if defined(__GLIBC__) && !defined(__UCLIBC__) |
459 POSIXBacktraceHelper<backtrace, backtrace_symbols>::DumpBacktrace(); | 376 POSIXBacktraceHelper<backtrace, backtrace_symbols>::DumpBacktrace(); |
460 #endif | 377 #endif |
461 } | 378 } |
462 | 379 |
463 | 380 |
464 class PosixMemoryMappedFile : public OS::MemoryMappedFile { | 381 class PosixMemoryMappedFile : public OS::MemoryMappedFile { |
465 public: | 382 public: |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 bool VirtualMemory::ReleaseRegion(void* base, size_t size) { | 677 bool VirtualMemory::ReleaseRegion(void* base, size_t size) { |
761 return munmap(base, size) == 0; | 678 return munmap(base, size) == 0; |
762 } | 679 } |
763 | 680 |
764 | 681 |
765 bool VirtualMemory::HasLazyCommits() { | 682 bool VirtualMemory::HasLazyCommits() { |
766 return true; | 683 return true; |
767 } | 684 } |
768 | 685 |
769 | 686 |
770 class Thread::PlatformData : public Malloced { | |
771 public: | |
772 PlatformData() : thread_(kNoThread) {} | |
773 | |
774 pthread_t thread_; // Thread handle for pthread. | |
775 }; | |
776 | |
777 Thread::Thread(const Options& options) | |
778 : data_(new PlatformData()), | |
779 stack_size_(options.stack_size()), | |
780 start_semaphore_(NULL) { | |
781 set_name(options.name()); | |
782 } | |
783 | |
784 | |
785 Thread::~Thread() { | |
786 delete data_; | |
787 } | |
788 | |
789 | |
790 static void* ThreadEntry(void* arg) { | |
791 Thread* thread = reinterpret_cast<Thread*>(arg); | |
792 // This is also initialized by the first argument to pthread_create() but we | |
793 // don't know which thread will run first (the original thread or the new | |
794 // one) so we initialize it here too. | |
795 #ifdef PR_SET_NAME | |
796 prctl(PR_SET_NAME, | |
797 reinterpret_cast<unsigned long>(thread->name()), // NOLINT | |
798 0, 0, 0); | |
799 #endif | |
800 thread->data()->thread_ = pthread_self(); | |
801 ASSERT(thread->data()->thread_ != kNoThread); | |
802 thread->NotifyStartedAndRun(); | |
803 return NULL; | |
804 } | |
805 | |
806 | |
807 void Thread::set_name(const char* name) { | |
808 strncpy(name_, name, sizeof(name_)); | |
809 name_[sizeof(name_) - 1] = '\0'; | |
810 } | |
811 | |
812 | |
813 void Thread::Start() { | |
814 pthread_attr_t* attr_ptr = NULL; | |
815 #if defined(__native_client__) | |
816 // use default stack size. | |
817 #else | |
818 pthread_attr_t attr; | |
819 if (stack_size_ > 0) { | |
820 pthread_attr_init(&attr); | |
821 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); | |
822 attr_ptr = &attr; | |
823 } | |
824 #endif | |
825 int result = pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); | |
826 CHECK_EQ(0, result); | |
827 ASSERT(data_->thread_ != kNoThread); | |
828 } | |
829 | |
830 | |
831 void Thread::Join() { | |
832 pthread_join(data_->thread_, NULL); | |
833 } | |
834 | |
835 | |
836 Thread::LocalStorageKey Thread::CreateThreadLocalKey() { | |
837 pthread_key_t key; | |
838 int result = pthread_key_create(&key, NULL); | |
839 USE(result); | |
840 ASSERT(result == 0); | |
841 return static_cast<LocalStorageKey>(key); | |
842 } | |
843 | |
844 | |
845 void Thread::DeleteThreadLocalKey(LocalStorageKey key) { | |
846 pthread_key_t pthread_key = static_cast<pthread_key_t>(key); | |
847 int result = pthread_key_delete(pthread_key); | |
848 USE(result); | |
849 ASSERT(result == 0); | |
850 } | |
851 | |
852 | |
853 void* Thread::GetThreadLocal(LocalStorageKey key) { | |
854 pthread_key_t pthread_key = static_cast<pthread_key_t>(key); | |
855 return pthread_getspecific(pthread_key); | |
856 } | |
857 | |
858 | |
859 void Thread::SetThreadLocal(LocalStorageKey key, void* value) { | |
860 pthread_key_t pthread_key = static_cast<pthread_key_t>(key); | |
861 pthread_setspecific(pthread_key, value); | |
862 } | |
863 | |
864 | |
865 class LinuxSemaphore : public Semaphore { | 687 class LinuxSemaphore : public Semaphore { |
866 public: | 688 public: |
867 explicit LinuxSemaphore(int count) { sem_init(&sem_, 0, count); } | 689 explicit LinuxSemaphore(int count) { sem_init(&sem_, 0, count); } |
868 virtual ~LinuxSemaphore() { sem_destroy(&sem_); } | 690 virtual ~LinuxSemaphore() { sem_destroy(&sem_); } |
869 | 691 |
870 virtual void Wait(); | 692 virtual void Wait(); |
871 virtual bool Wait(int timeout); | 693 virtual bool Wait(int timeout); |
872 virtual void Signal() { sem_post(&sem_); } | 694 virtual void Signal() { sem_post(&sem_); } |
873 private: | 695 private: |
874 sem_t sem_; | 696 sem_t sem_; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
939 limit_mutex = CreateMutex(); | 761 limit_mutex = CreateMutex(); |
940 } | 762 } |
941 | 763 |
942 | 764 |
943 void OS::TearDown() { | 765 void OS::TearDown() { |
944 delete limit_mutex; | 766 delete limit_mutex; |
945 } | 767 } |
946 | 768 |
947 | 769 |
948 } } // namespace v8::internal | 770 } } // namespace v8::internal |
OLD | NEW |