Bug 750989 - Pause Profiler during saving. r=mstange,jrmuizel

--HG--
extra : rebase_source : e1a6623d2a0de80423efb76c5b35e7734b119635
This commit is contained in:
Benoit Girard 2012-05-18 17:03:10 -04:00
Родитель 79b2854e72
Коммит 41af4c8c4b
5 изменённых файлов: 31 добавлений и 17 удалений

Просмотреть файл

@ -381,8 +381,14 @@ public:
} }
#endif #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; std::ofstream stream;
stream.open(buff); stream.open(buff);
t->SetPaused(true);
if (stream.is_open()) { if (stream.is_open()) {
stream << *(t->GetPrimaryThreadProfile()); stream << *(t->GetPrimaryThreadProfile());
stream << "h-" << GetSharedLibraryInfoString() << std::endl; stream << "h-" << GetSharedLibraryInfoString() << std::endl;
@ -391,6 +397,7 @@ public:
} else { } else {
LOG("Fail to open profile log file."); LOG("Fail to open profile log file.");
} }
t->SetPaused(false);
return NS_OK; return NS_OK;
} }
@ -422,8 +429,10 @@ JSObject* TableTicker::ToJSObject(JSContext *aCx)
b.DefineProperty(profile, "threads", threads); b.DefineProperty(profile, "threads", threads);
// For now we only have one thread // For now we only have one thread
SetPaused(true);
JSObject* threadSamples = GetPrimaryThreadProfile()->ToJSObject(aCx); JSObject* threadSamples = GetPrimaryThreadProfile()->ToJSObject(aCx);
b.ArrayPush(threads, threadSamples); b.ArrayPush(threads, threadSamples);
SetPaused(false);
return profile; return profile;
} }
@ -719,7 +728,9 @@ char* mozilla_sampler_get_profile()
} }
std::stringstream profile; std::stringstream profile;
t->SetPaused(true);
profile << *(t->GetPrimaryThreadProfile()); profile << *(t->GetPrimaryThreadProfile());
t->SetPaused(false);
std::string profileString = profile.str(); std::string profileString = profile.str();
char *rtn = (char*)malloc( (profileString.length() + 1) * sizeof(char) ); char *rtn = (char*)malloc( (profileString.length() + 1) * sizeof(char) );

Просмотреть файл

@ -139,28 +139,21 @@ class Sampler::PlatformData : public Malloced {
while (sampler_->IsActive()) { while (sampler_->IsActive()) {
sampler_->HandleSaveRequest(); sampler_->HandleSaveRequest();
if (!sampler_->IsPaused()) {
#ifdef XP_MACOSX #ifdef XP_MACOSX
pthread_kill(signal_receiver_, SIGPROF); pthread_kill(signal_receiver_, SIGPROF);
#else #else
// Glibc doesn't provide a wrapper for tgkill(2). // Glibc doesn't provide a wrapper for tgkill(2).
tgkill(vm_tgid_, vm_tid_, SIGPROF); tgkill(vm_tgid_, vm_tid_, SIGPROF);
#endif #endif
}
// Convert ms to us and subtract 100 us to compensate delays // Convert ms to us and subtract 100 us to compensate delays
// occuring during signal delivery. // occuring during signal delivery.
// TODO measure and confirm this. // TODO measure and confirm this.
const useconds_t interval = sampler_->interval_ * 1000 - 100; const useconds_t interval = sampler_->interval_ * 1000 - 100;
//int result = usleep(interval); //int result = usleep(interval);
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;
} }
} }
@ -189,7 +182,8 @@ static void* SenderEntry(void* arg) {
Sampler::Sampler(int interval, bool profiling) Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
active_(false) { active_(false),
paused_(false) {
data_ = new PlatformData(this); data_ = new PlatformData(this);
} }

Просмотреть файл

@ -223,7 +223,8 @@ class SamplerThread : public Thread {
// Implement Thread::Run(). // Implement Thread::Run().
virtual void Run() { virtual void Run() {
while (SamplerRegistry::sampler->IsActive()) { while (SamplerRegistry::sampler->IsActive()) {
SampleContext(SamplerRegistry::sampler); if (!SamplerRegistry::sampler->IsPaused())
SampleContext(SamplerRegistry::sampler);
OS::Sleep(interval_); OS::Sleep(interval_);
} }
} }
@ -295,7 +296,8 @@ Sampler::Sampler(int interval, bool profiling)
: // isolate_(isolate), : // isolate_(isolate),
interval_(interval), interval_(interval),
profiling_(profiling), profiling_(profiling),
active_(false) /*, active_(false),
paused_(false) /*,
samples_taken_(0)*/ { samples_taken_(0)*/ {
data_ = new PlatformData; data_ = new PlatformData;
} }

Просмотреть файл

@ -64,7 +64,8 @@ class SamplerThread : public Thread {
// Implement Thread::Run(). // Implement Thread::Run().
virtual void Run() { virtual void Run() {
while (sampler_->IsActive()) { while (sampler_->IsActive()) {
SampleContext(sampler_); if (!sampler_->IsPaused())
SampleContext(sampler_);
OS::Sleep(interval_); OS::Sleep(interval_);
} }
} }
@ -121,6 +122,7 @@ Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
active_(false), active_(false),
paused_(false),
data_(new PlatformData) { data_(new PlatformData) {
} }

Просмотреть файл

@ -211,6 +211,10 @@ class Sampler {
// Whether the sampler is running (that is, consumes resources). // Whether the sampler is running (that is, consumes resources).
bool IsActive() const { return active_; } 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; class PlatformData;
PlatformData* platform_data() { return data_; } PlatformData* platform_data() { return data_; }
@ -229,6 +233,7 @@ class Sampler {
const int interval_; const int interval_;
const bool profiling_; const bool profiling_;
Atomic32 paused_;
Atomic32 active_; Atomic32 active_;
PlatformData* data_; // Platform specific data. PlatformData* data_; // Platform specific data.
}; };