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

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

Issue 6759025: Version 3.2.6 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 years, 8 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.h ('k') | src/platform-linux.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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 double ceiling(double x) { 68 double ceiling(double x) {
69 // Correct as on OS X 69 // Correct as on OS X
70 if (-1.0 < x && x < 0.0) { 70 if (-1.0 < x && x < 0.0) {
71 return -0.0; 71 return -0.0;
72 } else { 72 } else {
73 return ceil(x); 73 return ceil(x);
74 } 74 }
75 } 75 }
76 76
77 77
78 static Mutex* limit_mutex = NULL;
79
80
78 void OS::Setup() { 81 void OS::Setup() {
79 // Seed the random number generator. 82 // Seed the random number generator.
80 // 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
81 // 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
82 // 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
83 // call this setup code within the same millisecond. 86 // call this setup code within the same millisecond.
84 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 87 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
85 srandom(static_cast<unsigned int>(seed)); 88 srandom(static_cast<unsigned int>(seed));
89 limit_mutex = CreateMutex();
86 } 90 }
87 91
88 92
89 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 93 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
90 __asm__ __volatile__("" : : : "memory"); 94 __asm__ __volatile__("" : : : "memory");
91 *ptr = value; 95 *ptr = value;
92 } 96 }
93 97
94 98
95 uint64_t OS::CpuFeaturesImpliedByPlatform() { 99 uint64_t OS::CpuFeaturesImpliedByPlatform() {
(...skipping 28 matching lines...) Expand all
124 // We keep the lowest and highest addresses mapped as a quick way of 128 // We keep the lowest and highest addresses mapped as a quick way of
125 // determining that pointers are outside the heap (used mostly in assertions 129 // determining that pointers are outside the heap (used mostly in assertions
126 // and verification). The estimate is conservative, ie, not all addresses in 130 // and verification). The estimate is conservative, ie, not all addresses in
127 // 'allocated' space are actually allocated to our heap. The range is 131 // 'allocated' space are actually allocated to our heap. The range is
128 // [lowest, highest), inclusive on the low and and exclusive on the high end. 132 // [lowest, highest), inclusive on the low and and exclusive on the high end.
129 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 133 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
130 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 134 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
131 135
132 136
133 static void UpdateAllocatedSpaceLimits(void* address, int size) { 137 static void UpdateAllocatedSpaceLimits(void* address, int size) {
138 ASSERT(limit_mutex != NULL);
139 ScopedLock lock(limit_mutex);
140
134 lowest_ever_allocated = Min(lowest_ever_allocated, address); 141 lowest_ever_allocated = Min(lowest_ever_allocated, address);
135 highest_ever_allocated = 142 highest_ever_allocated =
136 Max(highest_ever_allocated, 143 Max(highest_ever_allocated,
137 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 144 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
138 } 145 }
139 146
140 147
141 bool OS::IsOutsideAllocatedSpace(void* address) { 148 bool OS::IsOutsideAllocatedSpace(void* address) {
142 return address < lowest_ever_allocated || address >= highest_ever_allocated; 149 return address < lowest_ever_allocated || address >= highest_ever_allocated;
143 } 150 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 result = read(fd, buffer + bytes_read, 1); 300 result = read(fd, buffer + bytes_read, 1);
294 if (result < 1) break; 301 if (result < 1) break;
295 } while (buffer[bytes_read] != '\n'); 302 } while (buffer[bytes_read] != '\n');
296 buffer[bytes_read] = 0; 303 buffer[bytes_read] = 0;
297 // Ignore mappings that are not executable. 304 // Ignore mappings that are not executable.
298 if (buffer[3] != 'x') continue; 305 if (buffer[3] != 'x') continue;
299 char* start_of_path = index(buffer, '/'); 306 char* start_of_path = index(buffer, '/');
300 // There may be no filename in this line. Skip to next. 307 // There may be no filename in this line. Skip to next.
301 if (start_of_path == NULL) continue; 308 if (start_of_path == NULL) continue;
302 buffer[bytes_read] = 0; 309 buffer[bytes_read] = 0;
303 LOG(SharedLibraryEvent(start_of_path, start, end)); 310 LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end));
304 } 311 }
305 close(fd); 312 close(fd);
306 #endif 313 #endif
307 } 314 }
308 315
309 316
310 void OS::SignalCodeMovingGC() { 317 void OS::SignalCodeMovingGC() {
311 } 318 }
312 319
313 320
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 } 619 }
613 620
614 621
615 Semaphore* OS::CreateSemaphore(int count) { 622 Semaphore* OS::CreateSemaphore(int count) {
616 return new FreeBSDSemaphore(count); 623 return new FreeBSDSemaphore(count);
617 } 624 }
618 625
619 626
620 #ifdef ENABLE_LOGGING_AND_PROFILING 627 #ifdef ENABLE_LOGGING_AND_PROFILING
621 628
622 static Sampler* active_sampler_ = NULL;
623 static pthread_t vm_tid_ = NULL;
624
625
626 static pthread_t GetThreadID() { 629 static pthread_t GetThreadID() {
627 pthread_t thread_id = pthread_self(); 630 pthread_t thread_id = pthread_self();
628 return thread_id; 631 return thread_id;
629 } 632 }
630 633
631 634
632 class Sampler::PlatformData : public Malloced { 635 class Sampler::PlatformData : public Malloced {
633 public: 636 public:
634 enum SleepInterval { 637 PlatformData() : vm_tid_(GetThreadID()) {}
635 FULL_INTERVAL,
636 HALF_INTERVAL
637 };
638 638
639 explicit PlatformData(Sampler* sampler) 639 pthread_t vm_tid() const { return vm_tid_; }
640 : sampler_(sampler),
641 signal_handler_installed_(false),
642 signal_sender_launched_(false) {
643 }
644 640
645 void SignalSender() { 641 private:
646 while (sampler_->IsActive()) { 642 pthread_t vm_tid_;
647 if (rate_limiter_.SuspendIfNecessary()) continue;
648 if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
649 Sleep(FULL_INTERVAL);
650 RuntimeProfiler::NotifyTick();
651 } else {
652 if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
653 Sleep(FULL_INTERVAL);
654 }
655 }
656 }
657
658 void Sleep(SleepInterval full_or_half) {
659 // Convert ms to us and subtract 100 us to compensate delays
660 // occuring during signal delivery.
661 useconds_t interval = sampler_->interval_ * 1000 - 100;
662 if (full_or_half == HALF_INTERVAL) interval /= 2;
663 int result = usleep(interval);
664 #ifdef DEBUG
665 if (result != 0 && errno != EINTR) {
666 fprintf(stderr,
667 "SignalSender usleep error; interval = %u, errno = %d\n",
668 interval,
669 errno);
670 ASSERT(result == 0 || errno == EINTR);
671 }
672 #endif
673 USE(result);
674 }
675
676 Sampler* sampler_;
677 bool signal_handler_installed_;
678 struct sigaction old_signal_handler_;
679 struct itimerval old_timer_value_;
680 bool signal_sender_launched_;
681 pthread_t signal_sender_thread_;
682 RuntimeProfilerRateLimiter rate_limiter_;
683 }; 643 };
684 644
685 645
686 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 646 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
687 USE(info); 647 USE(info);
688 if (signal != SIGPROF) return; 648 if (signal != SIGPROF) return;
689 if (active_sampler_ == NULL) return; 649 Isolate* isolate = Isolate::UncheckedCurrent();
690 if (!active_sampler_->IsActive()) { 650 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
691 // Restore old signal handler 651 // We require a fully initialized and entered isolate.
692 Sampler::PlatformData* data = active_sampler_->data();
693 if (data->signal_handler_installed_) {
694 sigaction(SIGPROF, &data->old_signal_handler_, 0);
695 data->signal_handler_installed_ = false;
696 }
697 return; 652 return;
698 } 653 }
699 654 Sampler* sampler = isolate->logger()->sampler();
700 if (vm_tid_ != GetThreadID()) return; 655 if (sampler == NULL || !sampler->IsActive()) return;
701 656
702 TickSample sample_obj; 657 TickSample sample_obj;
703 TickSample* sample = CpuProfiler::TickSampleEvent(); 658 TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
704 if (sample == NULL) sample = &sample_obj; 659 if (sample == NULL) sample = &sample_obj;
705 660
706 // Extracting the sample from the context is extremely machine dependent. 661 // Extracting the sample from the context is extremely machine dependent.
707 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 662 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
708 mcontext_t& mcontext = ucontext->uc_mcontext; 663 mcontext_t& mcontext = ucontext->uc_mcontext;
664 sample->state = isolate->current_vm_state();
709 #if V8_HOST_ARCH_IA32 665 #if V8_HOST_ARCH_IA32
710 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip); 666 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip);
711 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp); 667 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp);
712 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp); 668 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp);
713 #elif V8_HOST_ARCH_X64 669 #elif V8_HOST_ARCH_X64
714 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip); 670 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip);
715 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp); 671 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp);
716 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp); 672 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp);
717 #elif V8_HOST_ARCH_ARM 673 #elif V8_HOST_ARCH_ARM
718 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15); 674 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
719 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13); 675 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
720 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11); 676 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
721 #endif 677 #endif
722 active_sampler_->SampleStack(sample); 678 sampler->SampleStack(sample);
723 active_sampler_->Tick(sample); 679 sampler->Tick(sample);
724 } 680 }
725 681
726 682
727 static void* SenderEntry(void* arg) { 683 class SignalSender : public Thread {
728 Sampler::PlatformData* data = 684 public:
729 reinterpret_cast<Sampler::PlatformData*>(arg); 685 enum SleepInterval {
730 data->SignalSender(); 686 HALF_INTERVAL,
731 return 0; 687 FULL_INTERVAL
732 } 688 };
689
690 explicit SignalSender(int interval)
691 : Thread(NULL, "SignalSender"),
692 interval_(interval) {}
693
694 static void AddActiveSampler(Sampler* sampler) {
695 ScopedLock lock(mutex_);
696 SamplerRegistry::AddActiveSampler(sampler);
697 if (instance_ == NULL) {
698 // Install a signal handler.
699 struct sigaction sa;
700 sa.sa_sigaction = ProfilerSignalHandler;
701 sigemptyset(&sa.sa_mask);
702 sa.sa_flags = SA_RESTART | SA_SIGINFO;
703 signal_handler_installed_ =
704 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
705
706 // Start a thread that sends SIGPROF signal to VM threads.
707 instance_ = new SignalSender(sampler->interval());
708 instance_->Start();
709 } else {
710 ASSERT(instance_->interval_ == sampler->interval());
711 }
712 }
713
714 static void RemoveActiveSampler(Sampler* sampler) {
715 ScopedLock lock(mutex_);
716 SamplerRegistry::RemoveActiveSampler(sampler);
717 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
718 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
719 instance_->Join();
720 delete instance_;
721 instance_ = NULL;
722
723 // Restore the old signal handler.
724 if (signal_handler_installed_) {
725 sigaction(SIGPROF, &old_signal_handler_, 0);
726 signal_handler_installed_ = false;
727 }
728 }
729 }
730
731 // Implement Thread::Run().
732 virtual void Run() {
733 SamplerRegistry::State state;
734 while ((state = SamplerRegistry::GetState()) !=
735 SamplerRegistry::HAS_NO_SAMPLERS) {
736 bool cpu_profiling_enabled =
737 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
738 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
739 // When CPU profiling is enabled both JavaScript and C++ code is
740 // profiled. We must not suspend.
741 if (!cpu_profiling_enabled) {
742 if (rate_limiter_.SuspendIfNecessary()) continue;
743 }
744 if (cpu_profiling_enabled && runtime_profiler_enabled) {
745 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
746 return;
747 }
748 Sleep(HALF_INTERVAL);
749 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
750 return;
751 }
752 Sleep(HALF_INTERVAL);
753 } else {
754 if (cpu_profiling_enabled) {
755 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
756 this)) {
757 return;
758 }
759 }
760 if (runtime_profiler_enabled) {
761 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
762 NULL)) {
763 return;
764 }
765 }
766 Sleep(FULL_INTERVAL);
767 }
768 }
769 }
770
771 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
772 if (!sampler->IsProfiling()) return;
773 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
774 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
775 }
776
777 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
778 if (!sampler->isolate()->IsInitialized()) return;
779 sampler->isolate()->runtime_profiler()->NotifyTick();
780 }
781
782 void SendProfilingSignal(pthread_t tid) {
783 if (!signal_handler_installed_) return;
784 pthread_kill(tid, SIGPROF);
785 }
786
787 void Sleep(SleepInterval full_or_half) {
788 // Convert ms to us and subtract 100 us to compensate delays
789 // occuring during signal delivery.
790 useconds_t interval = interval_ * 1000 - 100;
791 if (full_or_half == HALF_INTERVAL) interval /= 2;
792 int result = usleep(interval);
793 #ifdef DEBUG
794 if (result != 0 && errno != EINTR) {
795 fprintf(stderr,
796 "SignalSender usleep error; interval = %u, errno = %d\n",
797 interval,
798 errno);
799 ASSERT(result == 0 || errno == EINTR);
800 }
801 #endif
802 USE(result);
803 }
804
805 const int interval_;
806 RuntimeProfilerRateLimiter rate_limiter_;
807
808 // Protects the process wide state below.
809 static Mutex* mutex_;
810 static SignalSender* instance_;
811 static bool signal_handler_installed_;
812 static struct sigaction old_signal_handler_;
813
814 DISALLOW_COPY_AND_ASSIGN(SignalSender);
815 };
816
817 Mutex* SignalSender::mutex_ = OS::CreateMutex();
818 SignalSender* SignalSender::instance_ = NULL;
819 struct sigaction SignalSender::old_signal_handler_;
820 bool SignalSender::signal_handler_installed_ = false;
733 821
734 822
735 Sampler::Sampler(Isolate* isolate, int interval) 823 Sampler::Sampler(Isolate* isolate, int interval)
736 : isolate_(isolate), 824 : isolate_(isolate),
737 interval_(interval), 825 interval_(interval),
738 profiling_(false), 826 profiling_(false),
739 active_(false), 827 active_(false),
740 samples_taken_(0) { 828 samples_taken_(0) {
741 data_ = new PlatformData(this); 829 data_ = new PlatformData;
742 } 830 }
743 831
744 832
745 Sampler::~Sampler() { 833 Sampler::~Sampler() {
834 ASSERT(!IsActive());
746 delete data_; 835 delete data_;
747 } 836 }
748 837
749 838
750 void Sampler::Start() { 839 void Sampler::Start() {
751 // There can only be one active sampler at the time on POSIX
752 // platforms.
753 ASSERT(!IsActive()); 840 ASSERT(!IsActive());
754 vm_tid_ = GetThreadID();
755
756 // Request profiling signals.
757 struct sigaction sa;
758 sa.sa_sigaction = ProfilerSignalHandler;
759 sigemptyset(&sa.sa_mask);
760 sa.sa_flags = SA_SIGINFO;
761 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
762 data_->signal_handler_installed_ = true;
763
764 // Set the itimer to generate a tick for each interval.
765 itimerval itimer;
766 itimer.it_interval.tv_sec = interval_ / 1000;
767 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
768 itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
769 itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
770 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
771
772 // Set this sampler as the active sampler.
773 active_sampler_ = this;
774 SetActive(true); 841 SetActive(true);
775 842 SignalSender::AddActiveSampler(this);
776 // There's no way to send a signal to a thread on FreeBSD, but we can
777 // start a thread that uses the stack guard to interrupt the JS thread.
778 if (pthread_create(
779 &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
780 data_->signal_sender_launched_ = true;
781 }
782 } 843 }
783 844
784 845
785 void Sampler::Stop() { 846 void Sampler::Stop() {
786 // This sampler is no longer the active sampler. 847 ASSERT(IsActive());
787 active_sampler_ = NULL; 848 SignalSender::RemoveActiveSampler(this);
788 SetActive(false); 849 SetActive(false);
789
790 // Wait for signal sender termination (it will exit after setting
791 // active_ to false).
792 if (data_->signal_sender_launched_) {
793 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
794 pthread_join(data_->signal_sender_thread_, NULL);
795 data_->signal_sender_launched_ = false;
796 }
797 } 850 }
798 851
799 #endif // ENABLE_LOGGING_AND_PROFILING 852 #endif // ENABLE_LOGGING_AND_PROFILING
800 853
801 } } // namespace v8::internal 854 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform.h ('k') | src/platform-linux.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698