Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(122)

Side by Side Diff: src/platform-linux.cc

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-macos.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 #endif // def __GLIBC__ 51 #endif // def __GLIBC__
52 #include <strings.h> // index 52 #include <strings.h> // index
53 #include <errno.h> 53 #include <errno.h>
54 #include <stdarg.h> 54 #include <stdarg.h>
55 55
56 #undef MAP_TYPE 56 #undef MAP_TYPE
57 57
58 #include "v8.h" 58 #include "v8.h"
59 59
60 #include "platform.h" 60 #include "platform.h"
61 #include "top.h"
62 #include "v8threads.h" 61 #include "v8threads.h"
63 #include "vm-state-inl.h" 62 #include "vm-state-inl.h"
64 63
65 64
66 namespace v8 { 65 namespace v8 {
67 namespace internal { 66 namespace internal {
68 67
69 // 0 is never a valid thread id on Linux since tids and pids share a 68 // 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). 69 // name space and pid 0 is reserved (see man 2 kill).
71 static const pthread_t kNoThread = (pthread_t) 0; 70 static const pthread_t kNoThread = (pthread_t) 0;
72 71
73 72
74 double ceiling(double x) { 73 double ceiling(double x) {
75 return ceil(x); 74 return ceil(x);
76 } 75 }
77 76
78 77
78 static Mutex* limit_mutex = NULL;
79
80
79 void OS::Setup() { 81 void OS::Setup() {
80 // Seed the random number generator. 82 // Seed the random number generator.
81 // Convert the current time to a 64-bit integer first, before converting it 83 // Convert the current time to a 64-bit integer first, before converting it
82 // to an unsigned. Going directly can cause an overflow and the seed to be 84 // to an unsigned. Going directly can cause an overflow and the seed to be
83 // set to all ones. The seed will be identical for different instances that 85 // set to all ones. The seed will be identical for different instances that
84 // call this setup code within the same millisecond. 86 // call this setup code within the same millisecond.
85 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 87 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
86 srandom(static_cast<unsigned int>(seed)); 88 srandom(static_cast<unsigned int>(seed));
89 limit_mutex = CreateMutex();
87 } 90 }
88 91
89 92
90 uint64_t OS::CpuFeaturesImpliedByPlatform() { 93 uint64_t OS::CpuFeaturesImpliedByPlatform() {
91 #if (defined(__VFP_FP__) && !defined(__SOFTFP__)) 94 #if (defined(__VFP_FP__) && !defined(__SOFTFP__))
92 // Here gcc is telling us that we are on an ARM and gcc is assuming that we 95 // Here gcc is telling us that we are on an ARM and gcc is assuming that we
93 // have VFP3 instructions. If gcc can assume it then so can we. 96 // have VFP3 instructions. If gcc can assume it then so can we.
94 return 1u << VFP3; 97 return 1u << VFP3;
95 #elif CAN_USE_ARMV7_INSTRUCTIONS 98 #elif CAN_USE_ARMV7_INSTRUCTIONS
96 return 1u << ARMv7; 99 return 1u << ARMv7;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 // We keep the lowest and highest addresses mapped as a quick way of 222 // We keep the lowest and highest addresses mapped as a quick way of
220 // determining that pointers are outside the heap (used mostly in assertions 223 // determining that pointers are outside the heap (used mostly in assertions
221 // and verification). The estimate is conservative, ie, not all addresses in 224 // and verification). The estimate is conservative, ie, not all addresses in
222 // 'allocated' space are actually allocated to our heap. The range is 225 // 'allocated' space are actually allocated to our heap. The range is
223 // [lowest, highest), inclusive on the low and and exclusive on the high end. 226 // [lowest, highest), inclusive on the low and and exclusive on the high end.
224 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 227 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
225 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 228 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
226 229
227 230
228 static void UpdateAllocatedSpaceLimits(void* address, int size) { 231 static void UpdateAllocatedSpaceLimits(void* address, int size) {
232 ASSERT(limit_mutex != NULL);
233 ScopedLock lock(limit_mutex);
234
229 lowest_ever_allocated = Min(lowest_ever_allocated, address); 235 lowest_ever_allocated = Min(lowest_ever_allocated, address);
230 highest_ever_allocated = 236 highest_ever_allocated =
231 Max(highest_ever_allocated, 237 Max(highest_ever_allocated,
232 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 238 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
233 } 239 }
234 240
235 241
236 bool OS::IsOutsideAllocatedSpace(void* address) { 242 bool OS::IsOutsideAllocatedSpace(void* address) {
237 return address < lowest_ever_allocated || address >= highest_ever_allocated; 243 return address < lowest_ever_allocated || address >= highest_ever_allocated;
238 } 244 }
239 245
240 246
241 size_t OS::AllocateAlignment() { 247 size_t OS::AllocateAlignment() {
242 return sysconf(_SC_PAGESIZE); 248 return sysconf(_SC_PAGESIZE);
243 } 249 }
244 250
245 251
246 void* OS::Allocate(const size_t requested, 252 void* OS::Allocate(const size_t requested,
247 size_t* allocated, 253 size_t* allocated,
248 bool is_executable) { 254 bool is_executable) {
249 // TODO(805): Port randomization of allocated executable memory to Linux. 255 // TODO(805): Port randomization of allocated executable memory to Linux.
250 const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE)); 256 const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
251 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0); 257 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
252 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 258 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
253 if (mbase == MAP_FAILED) { 259 if (mbase == MAP_FAILED) {
254 LOG(StringEvent("OS::Allocate", "mmap failed")); 260 LOG(i::Isolate::Current(),
261 StringEvent("OS::Allocate", "mmap failed"));
255 return NULL; 262 return NULL;
256 } 263 }
257 *allocated = msize; 264 *allocated = msize;
258 UpdateAllocatedSpaceLimits(mbase, msize); 265 UpdateAllocatedSpaceLimits(mbase, msize);
259 return mbase; 266 return mbase;
260 } 267 }
261 268
262 269
263 void OS::Free(void* address, const size_t size) { 270 void OS::Free(void* address, const size_t size) {
264 // TODO(1240712): munmap has a return value which is ignored here. 271 // TODO(1240712): munmap has a return value which is ignored here.
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 // This function assumes that the layout of the file is as follows: 372 // This function assumes that the layout of the file is as follows:
366 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name] 373 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
367 // If we encounter an unexpected situation we abort scanning further entries. 374 // If we encounter an unexpected situation we abort scanning further entries.
368 FILE* fp = fopen("/proc/self/maps", "r"); 375 FILE* fp = fopen("/proc/self/maps", "r");
369 if (fp == NULL) return; 376 if (fp == NULL) return;
370 377
371 // Allocate enough room to be able to store a full file name. 378 // Allocate enough room to be able to store a full file name.
372 const int kLibNameLen = FILENAME_MAX + 1; 379 const int kLibNameLen = FILENAME_MAX + 1;
373 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen)); 380 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
374 381
382 i::Isolate* isolate = ISOLATE;
375 // This loop will terminate once the scanning hits an EOF. 383 // This loop will terminate once the scanning hits an EOF.
376 while (true) { 384 while (true) {
377 uintptr_t start, end; 385 uintptr_t start, end;
378 char attr_r, attr_w, attr_x, attr_p; 386 char attr_r, attr_w, attr_x, attr_p;
379 // Parse the addresses and permission bits at the beginning of the line. 387 // Parse the addresses and permission bits at the beginning of the line.
380 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break; 388 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
381 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break; 389 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
382 390
383 int c; 391 int c;
384 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') { 392 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
(...skipping 13 matching lines...) Expand all
398 406
399 // Drop the newline character read by fgets. We do not need to check 407 // Drop the newline character read by fgets. We do not need to check
400 // for a zero-length string because we know that we at least read the 408 // for a zero-length string because we know that we at least read the
401 // '/' character. 409 // '/' character.
402 lib_name[strlen(lib_name) - 1] = '\0'; 410 lib_name[strlen(lib_name) - 1] = '\0';
403 } else { 411 } else {
404 // No library name found, just record the raw address range. 412 // No library name found, just record the raw address range.
405 snprintf(lib_name, kLibNameLen, 413 snprintf(lib_name, kLibNameLen,
406 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end); 414 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
407 } 415 }
408 LOG(SharedLibraryEvent(lib_name, start, end)); 416 LOG(isolate, SharedLibraryEvent(lib_name, start, end));
409 } else { 417 } else {
410 // Entry not describing executable data. Skip to end of line to setup 418 // Entry not describing executable data. Skip to end of line to setup
411 // reading the next entry. 419 // reading the next entry.
412 do { 420 do {
413 c = getc(fp); 421 c = getc(fp);
414 } while ((c != EOF) && (c != '\n')); 422 } while ((c != EOF) && (c != '\n'));
415 if (c == EOF) break; 423 if (c == EOF) break;
416 } 424 }
417 } 425 }
418 free(lib_name); 426 free(lib_name);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 bool ThreadHandle::IsSelf() const { 566 bool ThreadHandle::IsSelf() const {
559 return pthread_equal(data_->thread_, pthread_self()); 567 return pthread_equal(data_->thread_, pthread_self());
560 } 568 }
561 569
562 570
563 bool ThreadHandle::IsValid() const { 571 bool ThreadHandle::IsValid() const {
564 return data_->thread_ != kNoThread; 572 return data_->thread_ != kNoThread;
565 } 573 }
566 574
567 575
568 Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) { 576 Thread::Thread(Isolate* isolate)
577 : ThreadHandle(ThreadHandle::INVALID),
578 isolate_(isolate) {
569 set_name("v8:<unknown>"); 579 set_name("v8:<unknown>");
570 } 580 }
571 581
572 582
573 Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) { 583 Thread::Thread(Isolate* isolate, const char* name)
584 : ThreadHandle(ThreadHandle::INVALID),
585 isolate_(isolate) {
574 set_name(name); 586 set_name(name);
575 } 587 }
576 588
577 589
578 Thread::~Thread() { 590 Thread::~Thread() {
579 } 591 }
580 592
581 593
582 static void* ThreadEntry(void* arg) { 594 static void* ThreadEntry(void* arg) {
583 Thread* thread = reinterpret_cast<Thread*>(arg); 595 Thread* thread = reinterpret_cast<Thread*>(arg);
584 // This is also initialized by the first argument to pthread_create() but we 596 // 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 597 // don't know which thread will run first (the original thread or the new
586 // one) so we initialize it here too. 598 // one) so we initialize it here too.
587 prctl(PR_SET_NAME, 599 prctl(PR_SET_NAME,
588 reinterpret_cast<unsigned long>(thread->name()), // NOLINT 600 reinterpret_cast<unsigned long>(thread->name()), // NOLINT
589 0, 0, 0); 601 0, 0, 0);
590 thread->thread_handle_data()->thread_ = pthread_self(); 602 thread->thread_handle_data()->thread_ = pthread_self();
591 ASSERT(thread->IsValid()); 603 ASSERT(thread->IsValid());
604 Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
592 thread->Run(); 605 thread->Run();
593 return NULL; 606 return NULL;
594 } 607 }
595 608
596 609
597 void Thread::set_name(const char* name) { 610 void Thread::set_name(const char* name) {
598 strncpy(name_, name, sizeof(name_)); 611 strncpy(name_, name, sizeof(name_));
599 name_[sizeof(name_) - 1] = '\0'; 612 name_[sizeof(name_) - 1] = '\0';
600 } 613 }
601 614
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 } 768 }
756 769
757 770
758 Semaphore* OS::CreateSemaphore(int count) { 771 Semaphore* OS::CreateSemaphore(int count) {
759 return new LinuxSemaphore(count); 772 return new LinuxSemaphore(count);
760 } 773 }
761 774
762 775
763 #ifdef ENABLE_LOGGING_AND_PROFILING 776 #ifdef ENABLE_LOGGING_AND_PROFILING
764 777
765 static Sampler* active_sampler_ = NULL;
766 static int vm_tid_ = 0;
767
768
769 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) 778 #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
770 // Android runs a fairly new Linux kernel, so signal info is there, 779 // Android runs a fairly new Linux kernel, so signal info is there,
771 // but the C library doesn't have the structs defined. 780 // but the C library doesn't have the structs defined.
772 781
773 struct sigcontext { 782 struct sigcontext {
774 uint32_t trap_no; 783 uint32_t trap_no;
775 uint32_t error_code; 784 uint32_t error_code;
776 uint32_t oldmask; 785 uint32_t oldmask;
777 uint32_t gregs[16]; 786 uint32_t gregs[16];
778 uint32_t arm_cpsr; 787 uint32_t arm_cpsr;
(...skipping 16 matching lines...) Expand all
795 static int GetThreadID() { 804 static int GetThreadID() {
796 // Glibc doesn't provide a wrapper for gettid(2). 805 // Glibc doesn't provide a wrapper for gettid(2).
797 return syscall(SYS_gettid); 806 return syscall(SYS_gettid);
798 } 807 }
799 808
800 809
801 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 810 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
802 #ifndef V8_HOST_ARCH_MIPS 811 #ifndef V8_HOST_ARCH_MIPS
803 USE(info); 812 USE(info);
804 if (signal != SIGPROF) return; 813 if (signal != SIGPROF) return;
805 if (active_sampler_ == NULL || !active_sampler_->IsActive()) return; 814 Isolate* isolate = Isolate::UncheckedCurrent();
806 if (vm_tid_ != GetThreadID()) return; 815 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
816 // We require a fully initialized and entered isolate.
817 return;
818 }
819 Sampler* sampler = isolate->logger()->sampler();
820 if (sampler == NULL || !sampler->IsActive()) return;
807 821
808 TickSample sample_obj; 822 TickSample sample_obj;
809 TickSample* sample = CpuProfiler::TickSampleEvent(); 823 TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
810 if (sample == NULL) sample = &sample_obj; 824 if (sample == NULL) sample = &sample_obj;
811 825
812 // Extracting the sample from the context is extremely machine dependent. 826 // Extracting the sample from the context is extremely machine dependent.
813 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 827 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
814 mcontext_t& mcontext = ucontext->uc_mcontext; 828 mcontext_t& mcontext = ucontext->uc_mcontext;
815 sample->state = Top::current_vm_state(); 829 sample->state = isolate->current_vm_state();
816 #if V8_HOST_ARCH_IA32 830 #if V8_HOST_ARCH_IA32
817 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]); 831 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
818 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]); 832 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
819 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]); 833 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
820 #elif V8_HOST_ARCH_X64 834 #elif V8_HOST_ARCH_X64
821 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]); 835 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
822 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]); 836 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
823 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]); 837 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
824 #elif V8_HOST_ARCH_ARM 838 #elif V8_HOST_ARCH_ARM
825 // An undefined macro evaluates to 0, so this applies to Android's Bionic also. 839 // An undefined macro evaluates to 0, so this applies to Android's Bionic also.
826 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3)) 840 #if (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
827 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]); 841 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
828 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]); 842 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
829 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]); 843 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
830 #else 844 #else
831 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc); 845 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
832 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp); 846 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
833 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp); 847 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
834 #endif 848 #endif
835 #elif V8_HOST_ARCH_MIPS 849 #elif V8_HOST_ARCH_MIPS
836 // Implement this on MIPS. 850 // Implement this on MIPS.
837 UNIMPLEMENTED(); 851 UNIMPLEMENTED();
838 #endif 852 #endif
839 active_sampler_->SampleStack(sample); 853 sampler->SampleStack(sample);
840 active_sampler_->Tick(sample); 854 sampler->Tick(sample);
841 #endif 855 #endif
842 } 856 }
843 857
844 858
845 class Sampler::PlatformData : public Malloced { 859 class Sampler::PlatformData : public Malloced {
846 public: 860 public:
861 PlatformData() : vm_tid_(GetThreadID()) {}
862
863 int vm_tid() const { return vm_tid_; }
864
865 private:
866 const int vm_tid_;
867 };
868
869
870 class SignalSender : public Thread {
871 public:
847 enum SleepInterval { 872 enum SleepInterval {
848 FULL_INTERVAL, 873 HALF_INTERVAL,
849 HALF_INTERVAL 874 FULL_INTERVAL
850 }; 875 };
851 876
852 explicit PlatformData(Sampler* sampler) 877 explicit SignalSender(int interval)
853 : sampler_(sampler), 878 : Thread(NULL), vm_tgid_(getpid()), interval_(interval) {}
854 signal_handler_installed_(false), 879
855 vm_tgid_(getpid()), 880 static void AddActiveSampler(Sampler* sampler) {
856 signal_sender_launched_(false) { 881 ScopedLock lock(mutex_);
882 SamplerRegistry::AddActiveSampler(sampler);
883 if (instance_ == NULL) {
884 // Install a signal handler.
885 struct sigaction sa;
886 sa.sa_sigaction = ProfilerSignalHandler;
887 sigemptyset(&sa.sa_mask);
888 sa.sa_flags = SA_RESTART | SA_SIGINFO;
889 signal_handler_installed_ =
890 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
891
892 // Start a thread that sends SIGPROF signal to VM threads.
893 instance_ = new SignalSender(sampler->interval());
894 instance_->Start();
895 } else {
896 ASSERT(instance_->interval_ == sampler->interval());
897 }
857 } 898 }
858 899
859 void SignalSender() { 900 static void RemoveActiveSampler(Sampler* sampler) {
860 while (sampler_->IsActive()) { 901 ScopedLock lock(mutex_);
861 if (rate_limiter_.SuspendIfNecessary()) continue; 902 SamplerRegistry::RemoveActiveSampler(sampler);
862 if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) { 903 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
863 SendProfilingSignal(); 904 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
905 instance_->Join();
906 delete instance_;
907 instance_ = NULL;
908
909 // Restore the old signal handler.
910 if (signal_handler_installed_) {
911 sigaction(SIGPROF, &old_signal_handler_, 0);
912 signal_handler_installed_ = false;
913 }
914 }
915 }
916
917 // Implement Thread::Run().
918 virtual void Run() {
919 SamplerRegistry::State state = SamplerRegistry::GetState();
920 while (state != SamplerRegistry::HAS_NO_SAMPLERS) {
921 bool cpu_profiling_enabled =
922 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
923 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
924 // When CPU profiling is enabled both JavaScript and C++ code is
925 // profiled. We must not suspend.
926 if (!cpu_profiling_enabled) {
927 if (rate_limiter_.SuspendIfNecessary()) continue;
928 }
929 if (cpu_profiling_enabled && runtime_profiler_enabled) {
930 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
931 return;
932 }
864 Sleep(HALF_INTERVAL); 933 Sleep(HALF_INTERVAL);
865 RuntimeProfiler::NotifyTick(); 934 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
935 return;
936 }
866 Sleep(HALF_INTERVAL); 937 Sleep(HALF_INTERVAL);
867 } else { 938 } else {
868 if (sampler_->IsProfiling()) SendProfilingSignal(); 939 if (cpu_profiling_enabled) {
869 if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick(); 940 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
941 this)) {
942 return;
943 }
944 }
945 if (runtime_profiler_enabled) {
946 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
947 NULL)) {
948 return;
949 }
950 }
870 Sleep(FULL_INTERVAL); 951 Sleep(FULL_INTERVAL);
871 } 952 }
872 } 953 }
873 } 954 }
874 955
875 void SendProfilingSignal() { 956 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
957 if (!sampler->IsProfiling()) return;
958 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
959 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
960 }
961
962 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
963 if (!sampler->isolate()->IsInitialized()) return;
964 sampler->isolate()->runtime_profiler()->NotifyTick();
965 }
966
967 void SendProfilingSignal(int tid) {
876 if (!signal_handler_installed_) return; 968 if (!signal_handler_installed_) return;
877 // Glibc doesn't provide a wrapper for tgkill(2). 969 // Glibc doesn't provide a wrapper for tgkill(2).
878 syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF); 970 syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
879 } 971 }
880 972
881 void Sleep(SleepInterval full_or_half) { 973 void Sleep(SleepInterval full_or_half) {
882 // Convert ms to us and subtract 100 us to compensate delays 974 // Convert ms to us and subtract 100 us to compensate delays
883 // occuring during signal delivery. 975 // occuring during signal delivery.
884 useconds_t interval = sampler_->interval_ * 1000 - 100; 976 useconds_t interval = interval_ * 1000 - 100;
885 if (full_or_half == HALF_INTERVAL) interval /= 2; 977 if (full_or_half == HALF_INTERVAL) interval /= 2;
886 int result = usleep(interval); 978 int result = usleep(interval);
887 #ifdef DEBUG 979 #ifdef DEBUG
888 if (result != 0 && errno != EINTR) { 980 if (result != 0 && errno != EINTR) {
889 fprintf(stderr, 981 fprintf(stderr,
890 "SignalSender usleep error; interval = %u, errno = %d\n", 982 "SignalSender usleep error; interval = %u, errno = %d\n",
891 interval, 983 interval,
892 errno); 984 errno);
893 ASSERT(result == 0 || errno == EINTR); 985 ASSERT(result == 0 || errno == EINTR);
894 } 986 }
895 #endif 987 #endif
896 USE(result); 988 USE(result);
897 } 989 }
898 990
899 Sampler* sampler_; 991 const int vm_tgid_;
900 bool signal_handler_installed_; 992 const int interval_;
901 struct sigaction old_signal_handler_;
902 int vm_tgid_;
903 bool signal_sender_launched_;
904 pthread_t signal_sender_thread_;
905 RuntimeProfilerRateLimiter rate_limiter_; 993 RuntimeProfilerRateLimiter rate_limiter_;
994
995 // Protects the process wide state below.
996 static Mutex* mutex_;
997 static SignalSender* instance_;
998 static bool signal_handler_installed_;
999 static struct sigaction old_signal_handler_;
1000
1001 DISALLOW_COPY_AND_ASSIGN(SignalSender);
906 }; 1002 };
907 1003
908 1004
909 static void* SenderEntry(void* arg) { 1005 Mutex* SignalSender::mutex_ = OS::CreateMutex();
910 Sampler::PlatformData* data = 1006 SignalSender* SignalSender::instance_ = NULL;
911 reinterpret_cast<Sampler::PlatformData*>(arg); 1007 struct sigaction SignalSender::old_signal_handler_;
912 data->SignalSender(); 1008 bool SignalSender::signal_handler_installed_ = false;
913 return 0;
914 }
915 1009
916 1010
917 Sampler::Sampler(int interval) 1011 Sampler::Sampler(Isolate* isolate, int interval)
918 : interval_(interval), 1012 : isolate_(isolate),
1013 interval_(interval),
919 profiling_(false), 1014 profiling_(false),
920 active_(false), 1015 active_(false),
921 samples_taken_(0) { 1016 samples_taken_(0) {
922 data_ = new PlatformData(this); 1017 data_ = new PlatformData;
923 } 1018 }
924 1019
925 1020
926 Sampler::~Sampler() { 1021 Sampler::~Sampler() {
927 ASSERT(!data_->signal_sender_launched_); 1022 ASSERT(!IsActive());
928 delete data_; 1023 delete data_;
929 } 1024 }
930 1025
931 1026
932 void Sampler::Start() { 1027 void Sampler::Start() {
933 // There can only be one active sampler at the time on POSIX
934 // platforms.
935 ASSERT(!IsActive()); 1028 ASSERT(!IsActive());
936 vm_tid_ = GetThreadID();
937
938 // Request profiling signals.
939 struct sigaction sa;
940 sa.sa_sigaction = ProfilerSignalHandler;
941 sigemptyset(&sa.sa_mask);
942 sa.sa_flags = SA_RESTART | SA_SIGINFO;
943 data_->signal_handler_installed_ =
944 sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
945
946 // Start a thread that sends SIGPROF signal to VM thread.
947 // Sending the signal ourselves instead of relying on itimer provides
948 // much better accuracy.
949 SetActive(true); 1029 SetActive(true);
950 if (pthread_create( 1030 SignalSender::AddActiveSampler(this);
951 &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
952 data_->signal_sender_launched_ = true;
953 }
954
955 // Set this sampler as the active sampler.
956 active_sampler_ = this;
957 } 1031 }
958 1032
959 1033
960 void Sampler::Stop() { 1034 void Sampler::Stop() {
1035 ASSERT(IsActive());
1036 SignalSender::RemoveActiveSampler(this);
961 SetActive(false); 1037 SetActive(false);
962
963 // Wait for signal sender termination (it will exit after setting
964 // active_ to false).
965 if (data_->signal_sender_launched_) {
966 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
967 pthread_join(data_->signal_sender_thread_, NULL);
968 data_->signal_sender_launched_ = false;
969 }
970
971 // Restore old signal handler
972 if (data_->signal_handler_installed_) {
973 sigaction(SIGPROF, &data_->old_signal_handler_, 0);
974 data_->signal_handler_installed_ = false;
975 }
976
977 // This sampler is no longer the active sampler.
978 active_sampler_ = NULL;
979 } 1038 }
980 1039
981
982 #endif // ENABLE_LOGGING_AND_PROFILING 1040 #endif // ENABLE_LOGGING_AND_PROFILING
983 1041
984 } } // namespace v8::internal 1042 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698