author | Benoit Girard <b56girard@gmail.com> |
Fri, 18 May 2012 17:03:10 -0400 | |
changeset 99032 | fdea12fb00634da270f1cdbbd95437c2d4ce0d6b |
parent 99031 | 4110f744518b93ffc0ccd11ca6bad9ae7009e978 |
child 99033 | 68e2fd6845edbcf7476e788b1cb5e9edcae2c933 |
push id | 173 |
push user | lsblakk@mozilla.com |
push date | Fri, 24 Aug 2012 15:39:16 +0000 |
treeherder | mozilla-release@bcc45eb1fb41 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mstange, jrmuizel |
bugs | 750989 |
milestone | 15.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/tools/profiler/TableTicker.cpp +++ b/tools/profiler/TableTicker.cpp @@ -376,26 +376,33 @@ public: // Expand %TEMP% on Windows { char tmp[MAXPATHLEN]; ExpandEnvironmentStringsA(buff, tmp, mozilla::ArrayLength(tmp)); strcpy(buff, tmp); } #endif + // Pause the profiler during saving. + // This will prevent us from recording sampling + // regarding profile saving. This will also + // prevent bugs caused by the circular buffer not + // being thread safe. Bug 750989. std::ofstream stream; stream.open(buff); + t->SetPaused(true); if (stream.is_open()) { stream << *(t->GetPrimaryThreadProfile()); stream << "h-" << GetSharedLibraryInfoString() << std::endl; stream.close(); LOG("Saved to " FOLDER "profile_TYPE_PID.txt"); } else { LOG("Fail to open profile log file."); } + t->SetPaused(false); return NS_OK; } }; void TableTicker::HandleSaveRequest() { if (!mSaveRequested) @@ -417,18 +424,20 @@ JSObject* TableTicker::ToJSObject(JSCont // Put meta data // TODO: List things like feature, version number, profile time start/end // Lists the samples for each ThreadProfile JSObject *threads = b.CreateArray(); b.DefineProperty(profile, "threads", threads); // For now we only have one thread + SetPaused(true); JSObject* threadSamples = GetPrimaryThreadProfile()->ToJSObject(aCx); b.ArrayPush(threads, threadSamples); + SetPaused(false); return profile; } #ifdef USE_BACKTRACE void TableTicker::doBacktrace(ThreadProfile &aProfile, TickSample* aSample) { @@ -714,17 +723,19 @@ void mozilla_sampler_save() char* mozilla_sampler_get_profile() { TableTicker *t = tlsTicker.get(); if (!t) { return NULL; } std::stringstream profile; + t->SetPaused(true); profile << *(t->GetPrimaryThreadProfile()); + t->SetPaused(false); std::string profileString = profile.str(); char *rtn = (char*)malloc( (profileString.length() + 1) * sizeof(char) ); strcpy(rtn, profileString.c_str()); return rtn; } JSObject *mozilla_sampler_get_profile_data(JSContext *aCx)
--- a/tools/profiler/platform-linux.cc +++ b/tools/profiler/platform-linux.cc @@ -134,38 +134,31 @@ class Sampler::PlatformData : public Mal #endif { } void SignalSender() { while (sampler_->IsActive()) { sampler_->HandleSaveRequest(); + if (!sampler_->IsPaused()) { #ifdef XP_MACOSX - pthread_kill(signal_receiver_, SIGPROF); + pthread_kill(signal_receiver_, SIGPROF); #else - // Glibc doesn't provide a wrapper for tgkill(2). - tgkill(vm_tgid_, vm_tid_, SIGPROF); + // Glibc doesn't provide a wrapper for tgkill(2). + tgkill(vm_tgid_, vm_tid_, SIGPROF); #endif + } + // Convert ms to us and subtract 100 us to compensate delays // occuring during signal delivery. - // TODO measure and confirm this. const useconds_t interval = sampler_->interval_ * 1000 - 100; //int result = usleep(interval); usleep(interval); - // sometimes usleep is defined as returning void - int result = 0; -#ifdef DEBUG - if (result != 0 && errno != EINTR) { - LOG("SignalSender usleep error"); - ASSERT(result == 0 || errno == EINTR); - } -#endif - mozilla::unused << result; } } Sampler* sampler_; bool signal_handler_installed_; struct sigaction old_sigprof_signal_handler_; struct sigaction old_sigsave_signal_handler_; pid_t vm_tgid_; @@ -184,17 +177,18 @@ static void* SenderEntry(void* arg) { data->SignalSender(); return 0; } Sampler::Sampler(int interval, bool profiling) : interval_(interval), profiling_(profiling), - active_(false) { + active_(false), + paused_(false) { data_ = new PlatformData(this); } Sampler::~Sampler() { ASSERT(!data_->signal_sender_launched_); delete data_; }
--- a/tools/profiler/platform-macos.cc +++ b/tools/profiler/platform-macos.cc @@ -218,17 +218,18 @@ class SamplerThread : public Thread { instance_ = NULL; } */ } // Implement Thread::Run(). virtual void Run() { while (SamplerRegistry::sampler->IsActive()) { - SampleContext(SamplerRegistry::sampler); + if (!SamplerRegistry::sampler->IsPaused()) + SampleContext(SamplerRegistry::sampler); OS::Sleep(interval_); } } void SampleContext(Sampler* sampler) { thread_act_t profiled_thread = sampler->platform_data()->profiled_thread(); TickSample sample_obj; TickSample* sample = &sample_obj; @@ -290,17 +291,18 @@ class SamplerThread : public Thread { Mutex* SamplerThread::mutex_ = OS::CreateMutex(); SamplerThread* SamplerThread::instance_ = NULL; Sampler::Sampler(int interval, bool profiling) : // isolate_(isolate), interval_(interval), profiling_(profiling), - active_(false) /*, + active_(false), + paused_(false) /*, samples_taken_(0)*/ { data_ = new PlatformData; } Sampler::~Sampler() { ASSERT(!IsActive()); delete data_;
--- a/tools/profiler/platform-win32.cc +++ b/tools/profiler/platform-win32.cc @@ -59,17 +59,18 @@ class SamplerThread : public Thread { instance_->Join(); delete instance_; instance_ = NULL; } // Implement Thread::Run(). virtual void Run() { while (sampler_->IsActive()) { - SampleContext(sampler_); + if (!sampler_->IsPaused()) + SampleContext(sampler_); OS::Sleep(interval_); } } void SampleContext(Sampler* sampler) { HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); if (profiled_thread == NULL) return; @@ -116,16 +117,17 @@ class SamplerThread : public Thread { SamplerThread* SamplerThread::instance_ = NULL; Sampler::Sampler(int interval, bool profiling) : interval_(interval), profiling_(profiling), active_(false), + paused_(false), data_(new PlatformData) { } Sampler::~Sampler() { ASSERT(!IsActive()); delete data_; }
--- a/tools/profiler/platform.h +++ b/tools/profiler/platform.h @@ -206,16 +206,20 @@ class Sampler { void Stop(); // Is the sampler used for profiling? bool IsProfiling() const { return profiling_; } // Whether the sampler is running (that is, consumes resources). bool IsActive() const { return active_; } + // Low overhead way to stop the sampler from ticking + bool IsPaused() const { return paused_; } + void SetPaused(bool value) { NoBarrier_Store(&paused_, value); } + class PlatformData; PlatformData* platform_data() { return data_; } // If we move the backtracing code into the platform files we won't // need to have these hacks #ifdef XP_WIN // xxxehsan sucky hack :( @@ -224,12 +228,13 @@ class Sampler { #ifdef XP_MACOSX static pthread_t GetProfiledThread(PlatformData*); #endif private: void SetActive(bool value) { NoBarrier_Store(&active_, value); } const int interval_; const bool profiling_; + Atomic32 paused_; Atomic32 active_; PlatformData* data_; // Platform specific data. };