From 3cfb103f723d06db7781908f6d9d8f790f117d8b Mon Sep 17 00:00:00 2001 From: Iris Hsiao Date: Mon, 24 Apr 2017 16:50:50 +0800 Subject: [PATCH] Backed out 6 changesets (bug 1358074) for Assertion failure: NS_IsMainThread and valgrind failures Backed out changeset c3f35f8a1f21 (bug 1358074) Backed out changeset 1d214f8ac8fd (bug 1358074) Backed out changeset 3221b215b080 (bug 1358074) Backed out changeset adec21069065 (bug 1358074) Backed out changeset 9baa76979a71 (bug 1358074) Backed out changeset 8375b7a4be08 (bug 1358074) --- tools/profiler/core/ThreadInfo.h | 4 +- .../profiler/core/platform-linux-android.cpp | 14 +- tools/profiler/core/platform-macos.cpp | 8 +- tools/profiler/core/platform-win32.cpp | 8 +- tools/profiler/core/platform.cpp | 294 +++++++++--------- tools/profiler/public/GeckoProfiler.h | 18 +- 6 files changed, 181 insertions(+), 165 deletions(-) diff --git a/tools/profiler/core/ThreadInfo.h b/tools/profiler/core/ThreadInfo.h index bdf243e92b3c..989ee98ba30f 100644 --- a/tools/profiler/core/ThreadInfo.h +++ b/tools/profiler/core/ThreadInfo.h @@ -90,8 +90,8 @@ private: // This is only used for the main thread. mozilla::Maybe mResponsiveness; - // When sampling, this holds the generation number and offset in PS::mBuffer - // of the most recent sample for this thread. + // When sampling, this holds the generation number and offset in + // ProfilerState::mBuffer of the most recent sample for this thread. ProfileBuffer::LastSample mLastSample; }; diff --git a/tools/profiler/core/platform-linux-android.cpp b/tools/profiler/core/platform-linux-android.cpp index 5c2296a220cf..19913d589924 100644 --- a/tools/profiler/core/platform-linux-android.cpp +++ b/tools/profiler/core/platform-linux-android.cpp @@ -279,7 +279,7 @@ ThreadEntry(void* aArg) return nullptr; } -SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration, +SamplerThread::SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration, double aIntervalMilliseconds) : mActivityGeneration(aActivityGeneration) , mIntervalMicroseconds( @@ -343,7 +343,7 @@ SamplerThread::~SamplerThread() } void -SamplerThread::Stop(PSLockRef aLock) +SamplerThread::Stop(PS::LockRef aLock) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); @@ -356,7 +356,7 @@ SamplerThread::Stop(PSLockRef aLock) } void -SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock, +SamplerThread::SuspendAndSampleAndResumeThread(PS::LockRef aLock, TickSample& aSample) { // Only one sampler thread can be sampling at once. So we expect to have @@ -466,7 +466,7 @@ paf_prepare() MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); gPS->SetWasPaused(lock, gPS->IsPaused(lock)); gPS->SetIsPaused(lock, true); @@ -480,14 +480,14 @@ paf_parent() MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); gPS->SetIsPaused(lock, gPS->WasPaused(lock)); gPS->SetWasPaused(lock, false); } static void -PlatformInit(PSLockRef aLock) +PlatformInit(PS::LockRef aLock) { // Set up the fork handlers. pthread_atfork(paf_prepare, paf_parent, nullptr); @@ -496,7 +496,7 @@ PlatformInit(PSLockRef aLock) #else static void -PlatformInit(PSLockRef aLock) +PlatformInit(PS::LockRef aLock) { } diff --git a/tools/profiler/core/platform-macos.cpp b/tools/profiler/core/platform-macos.cpp index 6cfe210d87c2..715226f36f6f 100644 --- a/tools/profiler/core/platform-macos.cpp +++ b/tools/profiler/core/platform-macos.cpp @@ -101,7 +101,7 @@ ThreadEntry(void* aArg) return nullptr; } -SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration, +SamplerThread::SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration, double aIntervalMilliseconds) : mActivityGeneration(aActivityGeneration) , mIntervalMicroseconds( @@ -121,13 +121,13 @@ SamplerThread::~SamplerThread() } void -SamplerThread::Stop(PSLockRef aLock) +SamplerThread::Stop(PS::LockRef aLock) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); } void -SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock, +SamplerThread::SuspendAndSampleAndResumeThread(PS::LockRef aLock, TickSample& aSample) { thread_act_t samplee_thread = aSample.mPlatformData->ProfiledThread(); @@ -204,7 +204,7 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock, //////////////////////////////////////////////////////////////////////// static void -PlatformInit(PSLockRef aLock) +PlatformInit(PS::LockRef aLock) { } diff --git a/tools/profiler/core/platform-win32.cpp b/tools/profiler/core/platform-win32.cpp index 918c2c2ee73d..6c4f41cb7de7 100644 --- a/tools/profiler/core/platform-win32.cpp +++ b/tools/profiler/core/platform-win32.cpp @@ -98,7 +98,7 @@ ThreadEntry(void* aArg) return 0; } -SamplerThread::SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration, +SamplerThread::SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration, double aIntervalMilliseconds) : mActivityGeneration(aActivityGeneration) , mIntervalMicroseconds( @@ -139,7 +139,7 @@ SamplerThread::~SamplerThread() } void -SamplerThread::Stop(PSLockRef aLock) +SamplerThread::Stop(PS::LockRef aLock) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); @@ -157,7 +157,7 @@ SamplerThread::Stop(PSLockRef aLock) } void -SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock, +SamplerThread::SuspendAndSampleAndResumeThread(PS::LockRef aLock, TickSample& aSample) { HANDLE profiled_thread = aSample.mPlatformData->ProfiledThread(); @@ -229,7 +229,7 @@ SamplerThread::SuspendAndSampleAndResumeThread(PSLockRef aLock, //////////////////////////////////////////////////////////////////////// static void -PlatformInit(PSLockRef aLock) +PlatformInit(PS::LockRef aLock) { } diff --git a/tools/profiler/core/platform.cpp b/tools/profiler/core/platform.cpp index fddcabcf4ac5..55c66d689ed1 100644 --- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -110,33 +110,34 @@ class SamplerThread; // Per-thread state. MOZ_THREAD_LOCAL(PseudoStack *) tlsPseudoStack; -class PSMutex : public mozilla::StaticMutex {}; - -typedef mozilla::BaseAutoLock PSAutoLock; - -// Only functions that take a PSLockRef arg can modify this class's fields. -typedef const PSAutoLock& PSLockRef; - // This class contains most of the profiler's global state. gPS is the single // instance. Most profile operations can't do anything useful when gPS is not // instantiated, so we release-assert its non-nullness in all such operations. // // Accesses to gPS are guarded by gPSMutex. Every getter and setter takes a -// PSAutoLock reference as an argument as proof that the gPSMutex is currently -// locked. This makes it clear when gPSMutex is locked and helps avoid -// accidental unlocked accesses to global state. There are ways to circumvent -// this mechanism, but please don't do so without *very* good reason and a -// detailed explanation. +// PS::AutoLock reference as an argument as proof that the gPSMutex is +// currently locked. This makes it clear when gPSMutex is locked and helps +// avoid accidental unlocked accesses to global state. There are ways to +// circumvent this mechanism, but please don't do so without *very* good reason +// and a detailed explanation. // // Other from the lock protection, this class is essentially a thin wrapper and // contains very little "smarts" itself. // -class PS +class ProfilerState { public: + // Shorter names for local use. + class Mutex : public mozilla::StaticMutex {}; + + typedef mozilla::BaseAutoLock AutoLock; + + // Only functions that take a LockRef arg can modify this class's fields. + typedef const AutoLock& LockRef; + typedef std::vector ThreadVector; - PS() + ProfilerState() : mEntries(0) , mInterval(0) , mFeatureDisplayListDump(false) @@ -154,7 +155,7 @@ public: , mFeatureThreads(false) , mBuffer(nullptr) , mIsPaused(false) -#if defined(GP_OS_linux) +#if defined(GP_OS_linux) || defined(GP_OS_android) , mWasPaused(false) #endif , mSamplerThread(nullptr) @@ -167,18 +168,18 @@ public: {} #define GET_AND_SET(type_, name_) \ - type_ name_(PSLockRef) const { return m##name_; } \ - void Set##name_(PSLockRef, type_ a##name_) { m##name_ = a##name_; } + type_ name_(LockRef) const { return m##name_; } \ + void Set##name_(LockRef, type_ a##name_) { m##name_ = a##name_; } - GET_AND_SET(TimeStamp, ProcessStartTime) + GET_AND_SET(TimeStamp, StartTime) GET_AND_SET(int, Entries) GET_AND_SET(double, Interval) - Vector& Features(PSLockRef) { return mFeatures; } + Vector& Features(LockRef) { return mFeatures; } - Vector& Filters(PSLockRef) { return mFilters; } + Vector& ThreadNameFilters(LockRef) { return mThreadNameFilters; } GET_AND_SET(bool, FeatureDisplayListDump) GET_AND_SET(bool, FeatureGPU) @@ -196,13 +197,13 @@ public: GET_AND_SET(ProfileBuffer*, Buffer) - ThreadVector& LiveThreads(PSLockRef) { return mLiveThreads; } - ThreadVector& DeadThreads(PSLockRef) { return mDeadThreads; } + ThreadVector& LiveThreads(LockRef) { return mLiveThreads; } + ThreadVector& DeadThreads(LockRef) { return mDeadThreads; } - static bool IsActive(PSLockRef) { return sActivityGeneration > 0; } - static uint32_t ActivityGeneration(PSLockRef) { return sActivityGeneration; } - static void SetInactive(PSLockRef) { sActivityGeneration = 0; } - static void SetActive(PSLockRef) + static bool IsActive(LockRef) { return sActivityGeneration > 0; } + static uint32_t ActivityGeneration(LockRef) { return sActivityGeneration; } + static void SetInactive(LockRef) { sActivityGeneration = 0; } + static void SetActive(LockRef) { sActivityGeneration = sNextActivityGeneration; // On overflow, reset to 1 instead of 0, because 0 means inactive. @@ -213,7 +214,7 @@ public: GET_AND_SET(bool, IsPaused) -#if defined(GP_OS_linux) +#if defined(GP_OS_linux) || defined(GP_OS_android) GET_AND_SET(bool, WasPaused) #endif @@ -231,8 +232,8 @@ public: #undef GET_AND_SET private: - // The time that the process started. - mozilla::TimeStamp mProcessStartTime; + // When profiler_init() or profiler_start() was most recently called. + mozilla::TimeStamp mStartTime; // The number of entries in mBuffer. Zeroed when the profiler is inactive. int mEntries; @@ -247,7 +248,7 @@ private: // Substrings of names of threads we want to profile. Cleared when the // profiler is inactive - Vector mFilters; + Vector mThreadNameFilters; // Configuration flags derived from mFeatures. Cleared when the profiler is // inactive. @@ -305,7 +306,7 @@ private: // Is the profiler paused? False when the profiler is inactive. bool mIsPaused; -#if defined(GP_OS_linux) +#if defined(GP_OS_linux) || defined(GP_OS_android) // Used to record whether the profiler was paused just before forking. False // at all times except just before/after forking. bool mWasPaused; @@ -329,17 +330,17 @@ private: int mLatestRecordedFrameNumber; }; +// A shorter name for use within this compilation unit. +typedef ProfilerState PS; + uint32_t PS::sActivityGeneration = 0; uint32_t PS::sNextActivityGeneration = 1; -// The core profiler state. Null at process startup, it is set to a non-null -// value in profiler_init() and stays that way until profiler_shutdown() is -// called. Therefore it can be checked to determine if the profiler has been -// initialized but not yet shut down. -static PS* gPS = nullptr; +// The profiler state. Set by profiler_init(), cleared by profiler_shutdown(). +PS* gPS = nullptr; // The mutex that guards accesses to gPS. -static PSMutex gPSMutex; +static PS::Mutex gPSMutex; // The name of the main thread. static const char* const kMainThreadName = "GeckoMain"; @@ -472,7 +473,7 @@ AddDynamicCodeLocationTag(ProfileBuffer* aBuffer, const char* aStr) static const int SAMPLER_MAX_STRING_LENGTH = 128; static void -AddPseudoEntry(PSLockRef aLock, ProfileBuffer* aBuffer, +AddPseudoEntry(PS::LockRef aLock, ProfileBuffer* aBuffer, volatile js::ProfileEntry& entry, PseudoStack* stack, void* lastpc) { @@ -574,7 +575,7 @@ struct AutoWalkJSStack }; static void -MergeStacksIntoProfile(PSLockRef aLock, ProfileBuffer* aBuffer, +MergeStacksIntoProfile(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample, NativeStack& aNativeStack) { NotNull pseudoStack = aSample.mPseudoStack; @@ -758,7 +759,7 @@ MergeStacksIntoProfile(PSLockRef aLock, ProfileBuffer* aBuffer, // Update the JS context with the current profile sample buffer generation. // // Do not do this for synchronous samples, which use their own - // ProfileBuffers instead of the global one in PS. + // ProfileBuffers instead of the global one in ProfilerState. if (!aSample.mIsSynchronous && pseudoStack->mContext) { MOZ_ASSERT(aBuffer->mGeneration >= startBufferGen); uint32_t lapCount = aBuffer->mGeneration - startBufferGen; @@ -784,7 +785,7 @@ StackWalkCallback(uint32_t aFrameNumber, void* aPC, void* aSP, void* aClosure) } static void -DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer, +DoNativeBacktrace(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample) { void* pc_array[1000]; @@ -826,7 +827,7 @@ DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer, #ifdef USE_EHABI_STACKWALK static void -DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer, +DoNativeBacktrace(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample) { void* pc_array[1000]; @@ -915,7 +916,7 @@ ASAN_memcpy(void* aDst, const void* aSrc, size_t aLen) #endif static void -DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer, +DoNativeBacktrace(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample) { const mcontext_t* mc = @@ -1058,7 +1059,7 @@ DoNativeBacktrace(PSLockRef aLock, ProfileBuffer* aBuffer, #endif static void -DoSampleStackTrace(PSLockRef aLock, ProfileBuffer* aBuffer, +DoSampleStackTrace(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample) { NativeStack nativeStack = { nullptr, nullptr, 0, 0 }; @@ -1072,12 +1073,11 @@ DoSampleStackTrace(PSLockRef aLock, ProfileBuffer* aBuffer, // This function is called for each sampling period with the current program // counter. It is called within a signal and so must be re-entrant. static void -Tick(PSLockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample) +Tick(PS::LockRef aLock, ProfileBuffer* aBuffer, const TickSample& aSample) { aBuffer->addTagThreadId(aSample.mThreadId, aSample.mLastSample); - mozilla::TimeDuration delta = - aSample.mTimeStamp - gPS->ProcessStartTime(aLock); + mozilla::TimeDuration delta = aSample.mTimeStamp - gPS->StartTime(aLock); aBuffer->addTag(ProfileBufferEntry::Time(delta.ToMilliseconds())); NotNull pseudoStack = aSample.mPseudoStack; @@ -1186,13 +1186,13 @@ StreamNameAndThreadId(JSONWriter& aWriter, const char* aName, int aThreadId) #endif static void -StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter) +StreamTaskTracer(PS::LockRef aLock, SpliceableJSONWriter& aWriter) { #ifdef MOZ_TASK_TRACER aWriter.StartArrayProperty("data"); { UniquePtr> data = - mozilla::tasktracer::GetLoggedData(gPS->ProcessStartTime(aLock)); + mozilla::tasktracer::GetLoggedData(gPS->StartTime(aLock)); for (uint32_t i = 0; i < data->Length(); ++i) { aWriter.StringElement((data->ElementAt(i)).get()); } @@ -1221,7 +1221,7 @@ StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter) } static void -StreamMetaJSCustomObject(PSLockRef aLock, SpliceableJSONWriter& aWriter) +StreamMetaJSCustomObject(PS::LockRef aLock, SpliceableJSONWriter& aWriter) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); @@ -1241,10 +1241,10 @@ StreamMetaJSCustomObject(PSLockRef aLock, SpliceableJSONWriter& aWriter) aWriter.IntProperty("asyncstack", asyncStacks); // The "startTime" field holds the number of milliseconds since midnight - // January 1, 1970 GMT. This grotty code computes (Now - (Now - - // ProcessStartTime)) to convert gPS->ProcessStartTime() into that form. + // January 1, 1970 GMT. This grotty code computes (Now - (Now - StartTime)) + // to convert gPS->StartTime() into that form. mozilla::TimeDuration delta = - mozilla::TimeStamp::Now() - gPS->ProcessStartTime(aLock); + mozilla::TimeStamp::Now() - gPS->StartTime(aLock); aWriter.DoubleProperty( "startTime", static_cast(PR_Now()/1000.0 - delta.ToMilliseconds())); @@ -1353,9 +1353,7 @@ BuildJavaThreadJSObject(SpliceableJSONWriter& aWriter) #endif static void -locked_profiler_stream_json_for_this_process(PSLockRef aLock, - SpliceableJSONWriter& aWriter, - double aSinceTime) +locked_profiler_stream_json_for_this_process(PS::LockRef aLock, SpliceableJSONWriter& aWriter, double aSinceTime) { LOG("locked_profiler_stream_json_for_this_process"); @@ -1386,23 +1384,23 @@ locked_profiler_stream_json_for_this_process(PSLockRef aLock, { gPS->SetIsPaused(aLock, true); - const PS::ThreadVector& liveThreads = gPS->LiveThreads(aLock); - for (size_t i = 0; i < liveThreads.size(); i++) { - ThreadInfo* info = liveThreads.at(i); - if (!info->IsBeingProfiled()) { - continue; + const PS::ThreadVector& liveThreads = gPS->LiveThreads(aLock); + for (size_t i = 0; i < liveThreads.size(); i++) { + ThreadInfo* info = liveThreads.at(i); + if (!info->IsBeingProfiled()) { + continue; + } + info->StreamJSON(gPS->Buffer(aLock), aWriter, gPS->StartTime(aLock), + aSinceTime); } - info->StreamJSON(gPS->Buffer(aLock), aWriter, - gPS->ProcessStartTime(aLock), aSinceTime); - } - const PS::ThreadVector& deadThreads = gPS->DeadThreads(aLock); - for (size_t i = 0; i < deadThreads.size(); i++) { - ThreadInfo* info = deadThreads.at(i); - MOZ_ASSERT(info->IsBeingProfiled()); - info->StreamJSON(gPS->Buffer(aLock), aWriter, - gPS->ProcessStartTime(aLock), aSinceTime); - } + const PS::ThreadVector& deadThreads = gPS->DeadThreads(aLock); + for (size_t i = 0; i < deadThreads.size(); i++) { + ThreadInfo* info = deadThreads.at(i); + MOZ_ASSERT(info->IsBeingProfiled()); + info->StreamJSON(gPS->Buffer(aLock), aWriter, gPS->StartTime(aLock), + aSinceTime); + } #if defined(PROFILE_JAVA) if (gPS->FeatureJava(aLock)) { @@ -1431,7 +1429,7 @@ profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter, double aSin MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return false; @@ -1469,7 +1467,7 @@ ProfilerMarker::GetTime() const { } void ProfilerMarker::StreamJSON(SpliceableJSONWriter& aWriter, - const TimeStamp& aProcessStartTime, + const TimeStamp& aStartTime, UniqueStacks& aUniqueStacks) const { // Schema: @@ -1485,7 +1483,7 @@ void ProfilerMarker::StreamJSON(SpliceableJSONWriter& aWriter, if (mPayload) { aWriter.StartObjectElement(); { - mPayload->StreamPayload(aWriter, aProcessStartTime, aUniqueStacks); + mPayload->StreamPayload(aWriter, aStartTime, aUniqueStacks); } aWriter.EndObject(); } @@ -1560,19 +1558,19 @@ class SamplerThread { public: // Creates a sampler thread, but doesn't start it. - SamplerThread(PSLockRef aLock, uint32_t aActivityGeneration, + SamplerThread(PS::LockRef aLock, uint32_t aActivityGeneration, double aIntervalMilliseconds); ~SamplerThread(); // This runs on the sampler thread. It suspends and resumes the samplee // threads. - void SuspendAndSampleAndResumeThread(PSLockRef aLock, TickSample& aSample); + void SuspendAndSampleAndResumeThread(PS::LockRef aLock, TickSample& aSample); // This runs on (is!) the sampler thread. void Run(); // This runs on the main thread. - void Stop(PSLockRef aLock); + void Stop(PS::LockRef aLock); private: // The activity generation, for detecting when the sampler thread must stop. @@ -1626,7 +1624,7 @@ SamplerThread::Run() while (true) { // This scope is for |lock|. It ends before we sleep below. { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); // At this point profiler_stop() might have been called, and // profiler_start() might have been called on another thread. @@ -1656,9 +1654,9 @@ SamplerThread::Run() // cheaper than taking a new sample. if (info->Stack()->CanDuplicateLastSampleDueToSleep()) { bool dup_ok = - gPS->Buffer(lock)->DuplicateLastSample( - info->ThreadId(), gPS->ProcessStartTime(lock), - info->LastSample()); + gPS->Buffer(lock)->DuplicateLastSample(info->ThreadId(), + gPS->StartTime(lock), + info->LastSample()); if (dup_ok) { continue; } @@ -1759,7 +1757,7 @@ GeckoProfilerReporter::CollectReports(nsIHandleReportCallback* aHandleReport, #endif { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (gPS) { profSize = GeckoProfilerMallocSizeOf(gPS); @@ -1784,7 +1782,7 @@ GeckoProfilerReporter::CollectReports(nsIHandleReportCallback* aHandleReport, // Measurement of the following things may be added later if DMD finds it // is worthwhile: // - gPS->mFeatures - // - gPS->mFilters + // - gPS->mThreadNameFilters // - gPS->mLiveThreads itself (its elements' children are measured above) // - gPS->mDeadThreads itself (ditto) // - gPS->mInterposeObserver @@ -1798,8 +1796,8 @@ GeckoProfilerReporter::CollectReports(nsIHandleReportCallback* aHandleReport, MOZ_COLLECT_REPORT( "explicit/profiler/profiler-state", KIND_HEAP, UNITS_BYTES, profSize, - "Memory used by the Gecko Profiler's global state (excluding memory used " - "by LUL)."); + "Memory used by the Gecko Profiler's ProfilerState object (excluding " + "memory used by LUL)."); #if defined(USE_LUL_STACKWALK) MOZ_COLLECT_REPORT( @@ -1813,23 +1811,23 @@ GeckoProfilerReporter::CollectReports(nsIHandleReportCallback* aHandleReport, NS_IMPL_ISUPPORTS(GeckoProfilerReporter, nsIMemoryReporter) static bool -ThreadSelected(PSLockRef aLock, const char* aThreadName) +ThreadSelected(PS::LockRef aLock, const char* aThreadName) { // This function runs both on and off the main thread. MOZ_RELEASE_ASSERT(gPS); - const Vector& filters = gPS->Filters(aLock); + const Vector& threadNameFilters = gPS->ThreadNameFilters(aLock); - if (filters.empty()) { + if (threadNameFilters.empty()) { return true; } std::string name = aThreadName; std::transform(name.begin(), name.end(), name.begin(), ::tolower); - for (uint32_t i = 0; i < filters.length(); ++i) { - std::string filter = filters[i]; + for (uint32_t i = 0; i < threadNameFilters.length(); ++i) { + std::string filter = threadNameFilters[i]; std::transform(filter.begin(), filter.end(), filter.begin(), ::tolower); // Crude, non UTF-8 compatible, case insensitive substring search @@ -1842,7 +1840,7 @@ ThreadSelected(PSLockRef aLock, const char* aThreadName) } static bool -ShouldProfileThread(PSLockRef aLock, ThreadInfo* aInfo) +ShouldProfileThread(PS::LockRef aLock, ThreadInfo* aInfo) { // This function runs both on and off the main thread. @@ -1855,7 +1853,7 @@ ShouldProfileThread(PSLockRef aLock, ThreadInfo* aInfo) // Find the ThreadInfo for the current thread. On success, *aIndexOut is set to // the index if it is non-null. static ThreadInfo* -FindLiveThreadInfo(PSLockRef aLock, int* aIndexOut = nullptr) +FindLiveThreadInfo(PS::LockRef aLock, int* aIndexOut = nullptr) { // This function runs both on and off the main thread. @@ -1874,7 +1872,7 @@ FindLiveThreadInfo(PSLockRef aLock, int* aIndexOut = nullptr) } static void -locked_register_thread(PSLockRef aLock, const char* aName, void* stackTop) +locked_register_thread(PS::LockRef aLock, const char* aName, void* stackTop) { // This function runs both on and off the main thread. @@ -1908,7 +1906,7 @@ locked_register_thread(PSLockRef aLock, const char* aName, void* stackTop) static void NotifyProfilerStarted(const int aEntries, double aInterval, const char** aFeatures, uint32_t aFeatureCount, - const char** aFilters, uint32_t aFilterCount) + const char** aThreadNameFilters, uint32_t aFilterCount) { if (!CanNotifyObservers()) { return; @@ -1924,13 +1922,14 @@ NotifyProfilerStarted(const int aEntries, double aInterval, featuresArray.AppendElement(aFeatures[i]); } - nsTArray filtersArray; + nsTArray threadNameFiltersArray; for (size_t i = 0; i < aFilterCount; ++i) { - filtersArray.AppendElement(aFilters[i]); + threadNameFiltersArray.AppendElement(aThreadNameFilters[i]); } nsCOMPtr params = - new nsProfilerStartParams(aEntries, aInterval, featuresArray, filtersArray); + new nsProfilerStartParams(aEntries, aInterval, featuresArray, + threadNameFiltersArray); os->NotifyObservers(params, "profiler-started", nullptr); } @@ -1951,9 +1950,9 @@ NotifyObservers(const char* aTopic) } static void -locked_profiler_start(PSLockRef aLock, const int aEntries, double aInterval, +locked_profiler_start(PS::LockRef aLock, const int aEntries, double aInterval, const char** aFeatures, uint32_t aFeatureCount, - const char** aFilters, uint32_t aFilterCount); + const char** aThreadNameFilters, uint32_t aFilterCount); void profiler_init(void* aStackTop) @@ -1980,14 +1979,14 @@ profiler_init(void* aStackTop) } { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); // We've passed the possible failure point. Instantiate gPS, which // indicates that the profiler has initialized successfully. gPS = new PS(); bool ignore; - gPS->SetProcessStartTime(lock, mozilla::TimeStamp::ProcessCreation(ignore)); + gPS->SetStartTime(lock, mozilla::TimeStamp::ProcessCreation(ignore)); locked_register_thread(lock, kMainThreadName, aStackTop); @@ -2053,10 +2052,10 @@ profiler_init(void* aStackTop) } static void -locked_profiler_save_profile_to_file(PSLockRef aLock, const char* aFilename); +locked_profiler_save_profile_to_file(PS::LockRef aLock, const char* aFilename); static SamplerThread* -locked_profiler_stop(PSLockRef aLock); +locked_profiler_stop(PS::LockRef aLock); void profiler_shutdown() @@ -2070,7 +2069,7 @@ profiler_shutdown() // gPS is destroyed, in order to delete it. SamplerThread* samplerThread = nullptr; { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); // Save the profile on shutdown if requested. if (gPS->IsActive(lock)) { @@ -2161,7 +2160,7 @@ profiler_get_start_params(int* aEntries, double* aInterval, return; } - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); *aEntries = gPS->Entries(lock); *aInterval = gPS->Interval(lock); @@ -2172,15 +2171,15 @@ profiler_get_start_params(int* aEntries, double* aInterval, (*aFeatures)[i] = features[i].c_str(); } - const Vector& filters = gPS->Filters(lock); - MOZ_ALWAYS_TRUE(aFilters->resize(filters.length())); - for (uint32_t i = 0; i < filters.length(); ++i) { - (*aFilters)[i] = filters[i].c_str(); + const Vector& threadNameFilters = gPS->ThreadNameFilters(lock); + MOZ_ALWAYS_TRUE(aFilters->resize(threadNameFilters.length())); + for (uint32_t i = 0; i < threadNameFilters.length(); ++i) { + (*aFilters)[i] = threadNameFilters[i].c_str(); } } static void -locked_profiler_save_profile_to_file(PSLockRef aLock, const char* aFilename) +locked_profiler_save_profile_to_file(PS::LockRef aLock, const char* aFilename) { LOG("locked_profiler_save_profile_to_file(%s)", aFilename); @@ -2214,7 +2213,7 @@ profiler_save_profile_to_file(const char* aFilename) MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return; @@ -2278,7 +2277,7 @@ profiler_get_buffer_info_helper(uint32_t* aCurrentPosition, MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return; @@ -2301,9 +2300,9 @@ hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) } static void -locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval, +locked_profiler_start(PS::LockRef aLock, int aEntries, double aInterval, const char** aFeatures, uint32_t aFeatureCount, - const char** aFilters, uint32_t aFilterCount) + const char** aThreadNameFilters, uint32_t aFilterCount) { if (LOG_TEST) { LOG("locked_profiler_start"); @@ -2313,13 +2312,16 @@ locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval, LOG("- feature = %s", aFeatures[i]); } for (uint32_t i = 0; i < aFilterCount; i++) { - LOG("- threads = %s", aFilters[i]); + LOG("- threads = %s", aThreadNameFilters[i]); } } MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS && !gPS->IsActive(aLock)); + bool ignore; + gPS->SetStartTime(aLock, mozilla::TimeStamp::ProcessCreation(ignore)); + // Fall back to the default value if the passed-in value is unreasonable. int entries = aEntries > 0 ? aEntries : PROFILE_DEFAULT_ENTRIES; gPS->SetEntries(aLock, entries); @@ -2335,11 +2337,12 @@ locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval, features[i] = aFeatures[i]; } - // Deep copy aFilters. Must precede the ShouldProfileThread() call below. - Vector& filters = gPS->Filters(aLock); - MOZ_ALWAYS_TRUE(filters.resize(aFilterCount)); + // Deep copy aThreadNameFilters. Must precede the ShouldProfileThread() call + // below. + Vector& threadNameFilters = gPS->ThreadNameFilters(aLock); + MOZ_ALWAYS_TRUE(threadNameFilters.resize(aFilterCount)); for (uint32_t i = 0; i < aFilterCount; ++i) { - filters[i] = aFilters[i]; + threadNameFilters[i] = aThreadNameFilters[i]; } #define HAS_FEATURE(feature) hasFeature(aFeatures, aFeatureCount, feature) @@ -2438,7 +2441,7 @@ locked_profiler_start(PSLockRef aLock, int aEntries, double aInterval, void profiler_start(int aEntries, double aInterval, const char** aFeatures, uint32_t aFeatureCount, - const char** aFilters, uint32_t aFilterCount) + const char** aThreadNameFilters, uint32_t aFilterCount) { LOG("profiler_start"); @@ -2446,7 +2449,7 @@ profiler_start(int aEntries, double aInterval, SamplerThread* samplerThread = nullptr; { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); // Initialize if necessary. if (!gPS) { @@ -2459,7 +2462,7 @@ profiler_start(int aEntries, double aInterval, } locked_profiler_start(lock, aEntries, aInterval, aFeatures, aFeatureCount, - aFilters, aFilterCount); + aThreadNameFilters, aFilterCount); } // We do these operations with gPSMutex unlocked. The comments in @@ -2469,11 +2472,11 @@ profiler_start(int aEntries, double aInterval, delete samplerThread; } NotifyProfilerStarted(aEntries, aInterval, aFeatures, aFeatureCount, - aFilters, aFilterCount); + aThreadNameFilters, aFilterCount); } static MOZ_MUST_USE SamplerThread* -locked_profiler_stop(PSLockRef aLock) +locked_profiler_stop(PS::LockRef aLock) { LOG("locked_profiler_stop"); @@ -2551,7 +2554,7 @@ locked_profiler_stop(PSLockRef aLock) gPS->SetFeatureTaskTracer(aLock, false); gPS->SetFeatureThreads(aLock, false); - gPS->Filters(aLock).clear(); + gPS->ThreadNameFilters(aLock).clear(); gPS->Features(aLock).clear(); @@ -2572,7 +2575,7 @@ profiler_stop() SamplerThread* samplerThread; { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return; @@ -2604,7 +2607,7 @@ profiler_is_paused() MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return false; @@ -2622,7 +2625,7 @@ profiler_pause() MOZ_RELEASE_ASSERT(gPS); { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return; @@ -2643,7 +2646,7 @@ profiler_resume() MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); { if (!gPS->IsActive(lock)) { @@ -2664,7 +2667,7 @@ profiler_feature_active(const char* aName) MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock)) { return false; @@ -2696,7 +2699,7 @@ profiler_is_active() MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); return gPS->IsActive(lock); } @@ -2708,7 +2711,7 @@ profiler_set_frame_number(int aFrameNumber) MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); gPS->SetFrameNumber(lock, aFrameNumber); } @@ -2721,7 +2724,7 @@ profiler_register_thread(const char* aName, void* aGuessStackTop) MOZ_RELEASE_ASSERT(!NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); void* stackTop = GetStackTop(aGuessStackTop); locked_register_thread(lock, aName, stackTop); @@ -2733,7 +2736,7 @@ profiler_unregister_thread() MOZ_RELEASE_ASSERT(!NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); // We don't call PseudoStack::stopJSSampling() here; there's no point doing // that for a JS thread that is in the process of disappearing. @@ -2831,10 +2834,10 @@ profiler_time() MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); mozilla::TimeDuration delta = - mozilla::TimeStamp::Now() - gPS->ProcessStartTime(lock); + mozilla::TimeStamp::Now() - gPS->StartTime(lock); return delta.ToMilliseconds(); } @@ -2844,7 +2847,7 @@ profiler_get_backtrace() MOZ_RELEASE_ASSERT(NS_IsMainThread()); MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) { return nullptr; @@ -2907,7 +2910,7 @@ profiler_get_backtrace_noalloc(char *output, size_t outputSize) bool includeDynamicString = true; { - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); includeDynamicString = !gPS->FeaturePrivacy(lock); } @@ -2944,7 +2947,7 @@ profiler_get_backtrace_noalloc(char *output, size_t outputSize) } static void -locked_profiler_add_marker(PSLockRef aLock, const char* aMarker, +locked_profiler_add_marker(PS::LockRef aLock, const char* aMarker, ProfilerMarkerPayload* aPayload) { // This function runs both on and off the main thread. @@ -2963,7 +2966,7 @@ locked_profiler_add_marker(PSLockRef aLock, const char* aMarker, mozilla::TimeStamp origin = (payload && !payload->GetStartTime().IsNull()) ? payload->GetStartTime() : mozilla::TimeStamp::Now(); - mozilla::TimeDuration delta = origin - gPS->ProcessStartTime(aLock); + mozilla::TimeDuration delta = origin - gPS->StartTime(aLock); stack->addMarker(aMarker, payload.release(), delta.ToMilliseconds()); } @@ -2974,7 +2977,7 @@ profiler_add_marker(const char* aMarker, ProfilerMarkerPayload* aPayload) MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); // aPayload must be freed if we return early. mozilla::UniquePtr payload(aPayload); @@ -2994,7 +2997,7 @@ profiler_tracing(const char* aCategory, const char* aInfo, MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) { return; @@ -3012,7 +3015,7 @@ profiler_tracing(const char* aCategory, const char* aInfo, MOZ_RELEASE_ASSERT(gPS); - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (!gPS->IsActive(lock) || gPS->FeaturePrivacy(lock)) { return; @@ -3065,7 +3068,7 @@ profiler_clear_js_context() // On JS shut down, flush the current buffer as stringifying JIT samples // requires a live JSContext. - PSAutoLock lock(gPSMutex); + PS::AutoLock lock(gPSMutex); if (gPS->IsActive(lock)) { gPS->SetIsPaused(lock, true); @@ -3074,8 +3077,7 @@ profiler_clear_js_context() ThreadInfo* info = FindLiveThreadInfo(lock); MOZ_RELEASE_ASSERT(info); if (info->IsBeingProfiled()) { - info->FlushSamplesAndMarkers(gPS->Buffer(lock), - gPS->ProcessStartTime(lock)); + info->FlushSamplesAndMarkers(gPS->Buffer(lock), gPS->StartTime(lock)); } gPS->SetIsPaused(lock, false); diff --git a/tools/profiler/public/GeckoProfiler.h b/tools/profiler/public/GeckoProfiler.h index 264fdaaf8201..94c2d98b0d1f 100644 --- a/tools/profiler/public/GeckoProfiler.h +++ b/tools/profiler/public/GeckoProfiler.h @@ -289,8 +289,8 @@ PROFILER_FUNC(bool profiler_thread_is_sleeping(), false) // not. PROFILER_FUNC_VOID(profiler_js_interrupt_callback()) -// The number of milliseconds since the process started. Operates the same -// whether the profiler is active or inactive. +// Gets the time since the last profiler_init() or profiler_start() call. +// Operates the same whether the profiler is active or inactive. PROFILER_FUNC(double profiler_time(), 0) PROFILER_FUNC_VOID(profiler_log(const char *str)) @@ -329,6 +329,14 @@ class ProfilerMarkerPayload; // extern MOZ_THREAD_LOCAL(PseudoStack*) tlsPseudoStack; +class ProfilerState; + +// The core profiler state. Null at process startup, it is set to a non-null +// value in profiler_init() and stays that way until profiler_shutdown() is +// called. Therefore it can be checked to determine if the profiler has been +// initialized but not yet shut down. +extern ProfilerState* gPS; + #ifndef SAMPLE_FUNCTION_NAME # if defined(__GNUC__) || defined(_MSC_VER) # define SAMPLE_FUNCTION_NAME __FUNCTION__ @@ -347,6 +355,8 @@ profiler_call_enter(const char* aInfo, { // This function runs both on and off the main thread. + MOZ_RELEASE_ASSERT(gPS); + PseudoStack* stack = tlsPseudoStack.get(); if (!stack) { return stack; @@ -363,6 +373,8 @@ profiler_call_exit(void* aHandle) { // This function runs both on and off the main thread. + MOZ_RELEASE_ASSERT(gPS); + if (!aHandle) { return; } @@ -486,6 +498,8 @@ profiler_get_pseudo_stack(void) { // This function runs both on and off the main thread. + MOZ_RELEASE_ASSERT(gPS); + return tlsPseudoStack.get(); }