Bug 785440 - Move profiler_is_active() implementation (and RacyFeatures) into GeckoProfiler.h. r=njn

MozReview-Commit-ID: D8y5RK2t6N4

--HG--
extra : rebase_source : 50513145561a1123c47741cb845e9b4adcf104a0
extra : intermediate-source : 85c8d7e4a5eb1616d36d4ec7916e3b077da3b236
extra : source : 5dda2adf525363b32844ea8162235fae3b54d17d
This commit is contained in:
Markus Stange 2017-08-02 14:39:55 -04:00
Родитель b613ceee3f
Коммит 7a2c359a92
2 изменённых файлов: 67 добавлений и 56 удалений

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

@ -151,6 +151,7 @@
#endif #endif
using namespace mozilla; using namespace mozilla;
using mozilla::profiler::detail::RacyFeatures;
LazyLogModule gProfilerLog("prof"); LazyLogModule gProfilerLog("prof");
@ -600,50 +601,6 @@ uint32_t ActivePS::sNextGeneration = 0;
// The mutex that guards accesses to CorePS and ActivePS. // The mutex that guards accesses to CorePS and ActivePS.
static PSMutex gPSMutex; static PSMutex gPSMutex;
// The preferred way to check profiler activeness and features is via
// ActivePS(). However, that requires locking gPSMutex. There are some hot
// operations where absolute precision isn't required, so we duplicate the
// activeness/feature state in a lock-free manner in this class.
class RacyFeatures
{
public:
static void SetActive(uint32_t aFeatures)
{
sActiveAndFeatures = Active | aFeatures;
}
static void SetInactive() { sActiveAndFeatures = 0; }
static bool IsActive() { return uint32_t(sActiveAndFeatures) & Active; }
static bool IsActiveWithFeature(uint32_t aFeature)
{
uint32_t af = sActiveAndFeatures; // copy it first
return (af & Active) && (af & aFeature);
}
static bool IsActiveWithoutPrivacy()
{
uint32_t af = sActiveAndFeatures; // copy it first
return (af & Active) && !(af & ProfilerFeature::Privacy);
}
private:
static const uint32_t Active = 1u << 31;
// Ensure Active doesn't overlap with any of the feature bits.
#define NO_OVERLAP(n_, str_, Name_) \
static_assert(ProfilerFeature::Name_ != Active, "bad Active value");
PROFILER_FOR_EACH_FEATURE(NO_OVERLAP);
#undef NO_OVERLAP
// We combine the active bit with the feature bits so they can be read or
// written in a single atomic operation.
static Atomic<uint32_t> sActiveAndFeatures;
};
Atomic<uint32_t> RacyFeatures::sActiveAndFeatures(0); Atomic<uint32_t> RacyFeatures::sActiveAndFeatures(0);
// Each live thread has a ThreadInfo, and we store a reference to it in TLS. // Each live thread has a ThreadInfo, and we store a reference to it in TLS.
@ -3071,17 +3028,6 @@ profiler_feature_active(uint32_t aFeature)
return RacyFeatures::IsActiveWithFeature(aFeature); return RacyFeatures::IsActiveWithFeature(aFeature);
} }
bool
profiler_is_active()
{
// This function runs both on and off the main thread.
MOZ_RELEASE_ASSERT(CorePS::Exists());
// This function is hot enough that we use RacyFeatures, notActivePS.
return RacyFeatures::IsActive();
}
void void
profiler_register_thread(const char* aName, void* aGuessStackTop) profiler_register_thread(const char* aName, void* aGuessStackTop)
{ {

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

@ -142,6 +142,64 @@ struct ProfilerFeature
#undef DECLARE #undef DECLARE
}; };
#ifdef MOZ_GECKO_PROFILER
namespace mozilla {
namespace profiler {
namespace detail {
// RacyFeatures is only defined in this header file so that its methods can
// be inlined into profiler_is_active(). Please do not use anything from the
// detail namespace outside the profiler.
// Within the profiler's code, the preferred way to check profiler activeness
// and features is via ActivePS(). However, that requires locking gPSMutex.
// There are some hot operations where absolute precision isn't required, so we
// duplicate the activeness/feature state in a lock-free manner in this class.
class RacyFeatures
{
public:
static void SetActive(uint32_t aFeatures)
{
sActiveAndFeatures = Active | aFeatures;
}
static void SetInactive() { sActiveAndFeatures = 0; }
static bool IsActive() { return uint32_t(sActiveAndFeatures) & Active; }
static bool IsActiveWithFeature(uint32_t aFeature)
{
uint32_t af = sActiveAndFeatures; // copy it first
return (af & Active) && (af & aFeature);
}
static bool IsActiveWithoutPrivacy()
{
uint32_t af = sActiveAndFeatures; // copy it first
return (af & Active) && !(af & ProfilerFeature::Privacy);
}
private:
static const uint32_t Active = 1u << 31;
// Ensure Active doesn't overlap with any of the feature bits.
#define NO_OVERLAP(n_, str_, Name_) \
static_assert(ProfilerFeature::Name_ != Active, "bad Active value");
PROFILER_FOR_EACH_FEATURE(NO_OVERLAP);
#undef NO_OVERLAP
// We combine the active bit with the feature bits so they can be read or
// written in a single atomic operation.
static mozilla::Atomic<uint32_t> sActiveAndFeatures;
};
} // namespace detail
} // namespace profiler
} // namespace mozilla
#endif
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Start and stop the profiler // Start and stop the profiler
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -263,7 +321,14 @@ void profiler_clear_js_context();
// expensive data will end up being created but not used if another thread // expensive data will end up being created but not used if another thread
// stops the profiler between the CreateExpensiveData() and PROFILER_OPERATION // stops the profiler between the CreateExpensiveData() and PROFILER_OPERATION
// calls. // calls.
bool profiler_is_active(); inline bool profiler_is_active()
{
#ifdef MOZ_GECKO_PROFILER
return mozilla::profiler::detail::RacyFeatures::IsActive();
#else
return false;
#endif
}
// Is the profiler active and paused? Returns false if the profiler is inactive. // Is the profiler active and paused? Returns false if the profiler is inactive.
bool profiler_is_paused(); bool profiler_is_paused();