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

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

Issue 6677076: Merge up to bleeding_edge r7201 to isolates branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/isolates
Patch Set: Fix lint. 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.h ('k') | src/runtime.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 24 matching lines...) Expand all
35 #include <sys/resource.h> 35 #include <sys/resource.h>
36 #include <sys/types.h> 36 #include <sys/types.h>
37 #include <sys/ucontext.h> 37 #include <sys/ucontext.h>
38 #include <stdlib.h> 38 #include <stdlib.h>
39 39
40 #include <sys/types.h> // mmap & munmap 40 #include <sys/types.h> // mmap & munmap
41 #include <sys/mman.h> // mmap & munmap 41 #include <sys/mman.h> // mmap & munmap
42 #include <sys/stat.h> // open 42 #include <sys/stat.h> // open
43 #include <sys/fcntl.h> // open 43 #include <sys/fcntl.h> // open
44 #include <unistd.h> // getpagesize 44 #include <unistd.h> // getpagesize
45 // If you don't have execinfo.h then you need devel/libexecinfo from ports.
45 #include <execinfo.h> // backtrace, backtrace_symbols 46 #include <execinfo.h> // backtrace, backtrace_symbols
46 #include <strings.h> // index 47 #include <strings.h> // index
47 #include <errno.h> 48 #include <errno.h>
48 #include <stdarg.h> 49 #include <stdarg.h>
49 #include <limits.h> 50 #include <limits.h>
50 51
51 #undef MAP_TYPE 52 #undef MAP_TYPE
52 53
53 #include "v8.h" 54 #include "v8.h"
54 55
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 virtual int Lock() { 524 virtual int Lock() {
524 int result = pthread_mutex_lock(&mutex_); 525 int result = pthread_mutex_lock(&mutex_);
525 return result; 526 return result;
526 } 527 }
527 528
528 virtual int Unlock() { 529 virtual int Unlock() {
529 int result = pthread_mutex_unlock(&mutex_); 530 int result = pthread_mutex_unlock(&mutex_);
530 return result; 531 return result;
531 } 532 }
532 533
534 virtual bool TryLock() {
535 int result = pthread_mutex_trylock(&mutex_);
536 // Return false if the lock is busy and locking failed.
537 if (result == EBUSY) {
538 return false;
539 }
540 ASSERT(result == 0); // Verify no other errors.
541 return true;
542 }
543
533 private: 544 private:
534 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 545 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
535 }; 546 };
536 547
537 548
538 Mutex* OS::CreateMutex() { 549 Mutex* OS::CreateMutex() {
539 return new FreeBSDMutex(); 550 return new FreeBSDMutex();
540 } 551 }
541 552
542 553
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 603
593 604
594 Semaphore* OS::CreateSemaphore(int count) { 605 Semaphore* OS::CreateSemaphore(int count) {
595 return new FreeBSDSemaphore(count); 606 return new FreeBSDSemaphore(count);
596 } 607 }
597 608
598 609
599 #ifdef ENABLE_LOGGING_AND_PROFILING 610 #ifdef ENABLE_LOGGING_AND_PROFILING
600 611
601 static Sampler* active_sampler_ = NULL; 612 static Sampler* active_sampler_ = NULL;
613 static pthread_t vm_tid_ = NULL;
614
615
616 static pthread_t GetThreadID() {
617 pthread_t thread_id = pthread_self();
618 return thread_id;
619 }
620
621
622 class Sampler::PlatformData : public Malloced {
623 public:
624 enum SleepInterval {
625 FULL_INTERVAL,
626 HALF_INTERVAL
627 };
628
629 explicit PlatformData(Sampler* sampler)
630 : sampler_(sampler),
631 signal_handler_installed_(false),
632 signal_sender_launched_(false) {
633 }
634
635 void SignalSender() {
636 while (sampler_->IsActive()) {
637 if (rate_limiter_.SuspendIfNecessary()) continue;
638 if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
639 Sleep(FULL_INTERVAL);
640 RuntimeProfiler::NotifyTick();
641 } else {
642 if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
643 Sleep(FULL_INTERVAL);
644 }
645 }
646 }
647
648 void Sleep(SleepInterval full_or_half) {
649 // Convert ms to us and subtract 100 us to compensate delays
650 // occuring during signal delivery.
651 useconds_t interval = sampler_->interval_ * 1000 - 100;
652 if (full_or_half == HALF_INTERVAL) interval /= 2;
653 int result = usleep(interval);
654 #ifdef DEBUG
655 if (result != 0 && errno != EINTR) {
656 fprintf(stderr,
657 "SignalSender usleep error; interval = %u, errno = %d\n",
658 interval,
659 errno);
660 ASSERT(result == 0 || errno == EINTR);
661 }
662 #endif
663 USE(result);
664 }
665
666 Sampler* sampler_;
667 bool signal_handler_installed_;
668 struct sigaction old_signal_handler_;
669 struct itimerval old_timer_value_;
670 bool signal_sender_launched_;
671 pthread_t signal_sender_thread_;
672 RuntimeProfilerRateLimiter rate_limiter_;
673 };
674
602 675
603 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 676 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
604 USE(info); 677 USE(info);
605 if (signal != SIGPROF) return; 678 if (signal != SIGPROF) return;
606 if (active_sampler_ == NULL) return; 679 if (active_sampler_ == NULL) return;
607 680 if (!active_sampler_->IsActive()) {
608 TickSample sample; 681 // Restore old signal handler
609 682 Sampler::PlatformData* data = active_sampler_->data();
610 // We always sample the VM state. 683 if (data->signal_handler_installed_) {
611 sample.state = VMState::current_state(); 684 sigaction(SIGPROF, &data->old_signal_handler_, 0);
612 685 data->signal_handler_installed_ = false;
613 // If profiling, we extract the current pc and sp. 686 }
614 if (active_sampler_->IsProfiling()) { 687 return;
615 // Extracting the sample from the context is extremely machine dependent.
616 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
617 mcontext_t& mcontext = ucontext->uc_mcontext;
618 #if V8_HOST_ARCH_IA32
619 sample.pc = reinterpret_cast<Address>(mcontext.mc_eip);
620 sample.sp = reinterpret_cast<Address>(mcontext.mc_esp);
621 sample.fp = reinterpret_cast<Address>(mcontext.mc_ebp);
622 #elif V8_HOST_ARCH_X64
623 sample.pc = reinterpret_cast<Address>(mcontext.mc_rip);
624 sample.sp = reinterpret_cast<Address>(mcontext.mc_rsp);
625 sample.fp = reinterpret_cast<Address>(mcontext.mc_rbp);
626 #elif V8_HOST_ARCH_ARM
627 sample.pc = reinterpret_cast<Address>(mcontext.mc_r15);
628 sample.sp = reinterpret_cast<Address>(mcontext.mc_r13);
629 sample.fp = reinterpret_cast<Address>(mcontext.mc_r11);
630 #endif
631 active_sampler_->SampleStack(&sample);
632 } 688 }
633 689
634 active_sampler_->Tick(&sample); 690 if (vm_tid_ != GetThreadID()) return;
691
692 TickSample sample_obj;
693 TickSample* sample = CpuProfiler::TickSampleEvent();
694 if (sample == NULL) sample = &sample_obj;
695
696 // Extracting the sample from the context is extremely machine dependent.
697 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
698 mcontext_t& mcontext = ucontext->uc_mcontext;
699 #if V8_HOST_ARCH_IA32
700 sample->pc = reinterpret_cast<Address>(mcontext.mc_eip);
701 sample->sp = reinterpret_cast<Address>(mcontext.mc_esp);
702 sample->fp = reinterpret_cast<Address>(mcontext.mc_ebp);
703 #elif V8_HOST_ARCH_X64
704 sample->pc = reinterpret_cast<Address>(mcontext.mc_rip);
705 sample->sp = reinterpret_cast<Address>(mcontext.mc_rsp);
706 sample->fp = reinterpret_cast<Address>(mcontext.mc_rbp);
707 #elif V8_HOST_ARCH_ARM
708 sample->pc = reinterpret_cast<Address>(mcontext.mc_r15);
709 sample->sp = reinterpret_cast<Address>(mcontext.mc_r13);
710 sample->fp = reinterpret_cast<Address>(mcontext.mc_r11);
711 #endif
712 active_sampler_->SampleStack(sample);
713 active_sampler_->Tick(sample);
635 } 714 }
636 715
637 716
638 class Sampler::PlatformData : public Malloced { 717 static void* SenderEntry(void* arg) {
639 public: 718 Sampler::PlatformData* data =
640 PlatformData() { 719 reinterpret_cast<Sampler::PlatformData*>(arg);
641 signal_handler_installed_ = false; 720 data->SignalSender();
642 } 721 return 0;
643 722 }
644 bool signal_handler_installed_;
645 struct sigaction old_signal_handler_;
646 struct itimerval old_timer_value_;
647 };
648 723
649 724
650 Sampler::Sampler(Isolate* isolate, int interval) 725 Sampler::Sampler(Isolate* isolate, int interval)
651 : isolate_(isolate), 726 : isolate_(isolate),
652 interval_(interval), 727 interval_(interval),
653 profiling_(false), 728 profiling_(false),
654 active_(false), 729 active_(false),
655 samples_taken_(0) { 730 samples_taken_(0) {
656 data_ = new PlatformData(); 731 data_ = new PlatformData(this);
657 } 732 }
658 733
659 734
660 Sampler::~Sampler() { 735 Sampler::~Sampler() {
661 delete data_; 736 delete data_;
662 } 737 }
663 738
664 739
665 void Sampler::Start() { 740 void Sampler::Start() {
666 // There can only be one active sampler at the time on POSIX 741 // There can only be one active sampler at the time on POSIX
667 // platforms. 742 // platforms.
668 if (active_sampler_ != NULL) return; 743 ASSERT(!IsActive());
744 vm_tid_ = GetThreadID();
669 745
670 // Request profiling signals. 746 // Request profiling signals.
671 struct sigaction sa; 747 struct sigaction sa;
672 sa.sa_sigaction = ProfilerSignalHandler; 748 sa.sa_sigaction = ProfilerSignalHandler;
673 sigemptyset(&sa.sa_mask); 749 sigemptyset(&sa.sa_mask);
674 sa.sa_flags = SA_SIGINFO; 750 sa.sa_flags = SA_SIGINFO;
675 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; 751 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
676 data_->signal_handler_installed_ = true; 752 data_->signal_handler_installed_ = true;
677 753
678 // Set the itimer to generate a tick for each interval. 754 // Set the itimer to generate a tick for each interval.
679 itimerval itimer; 755 itimerval itimer;
680 itimer.it_interval.tv_sec = interval_ / 1000; 756 itimer.it_interval.tv_sec = interval_ / 1000;
681 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; 757 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
682 itimer.it_value.tv_sec = itimer.it_interval.tv_sec; 758 itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
683 itimer.it_value.tv_usec = itimer.it_interval.tv_usec; 759 itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
684 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); 760 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
685 761
686 // Set this sampler as the active sampler. 762 // Set this sampler as the active sampler.
687 active_sampler_ = this; 763 active_sampler_ = this;
688 active_ = true; 764 SetActive(true);
765
766 // There's no way to send a signal to a thread on FreeBSD, but we can
767 // start a thread that uses the stack guard to interrupt the JS thread.
768 if (pthread_create(
769 &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
770 data_->signal_sender_launched_ = true;
771 }
689 } 772 }
690 773
691 774
692 void Sampler::Stop() { 775 void Sampler::Stop() {
693 // Restore old signal handler
694 if (data_->signal_handler_installed_) {
695 setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
696 sigaction(SIGPROF, &data_->old_signal_handler_, 0);
697 data_->signal_handler_installed_ = false;
698 }
699
700 // This sampler is no longer the active sampler. 776 // This sampler is no longer the active sampler.
701 active_sampler_ = NULL; 777 active_sampler_ = NULL;
702 active_ = false; 778 SetActive(false);
779
780 // Wait for signal sender termination (it will exit after setting
781 // active_ to false).
782 if (data_->signal_sender_launched_) {
783 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
784 pthread_join(data_->signal_sender_thread_, NULL);
785 data_->signal_sender_launched_ = false;
786 }
703 } 787 }
704 788
705 #endif // ENABLE_LOGGING_AND_PROFILING 789 #endif // ENABLE_LOGGING_AND_PROFILING
706 790
707 } } // namespace v8::internal 791 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698