Bug 785440 - Move profiler_is_active() implementation (and RacyFeatures) into GeckoProfiler.h. r?njn
MozReview-Commit-ID: D8y5RK2t6N4
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -146,16 +146,17 @@
# define VALGRIND_MAKE_MEM_DEFINED(_addr,_len) ((void)0)
#endif
#if defined(GP_OS_linux) || defined(GP_OS_android)
#include <ucontext.h>
#endif
using namespace mozilla;
+using mozilla::profiler::detail::RacyFeatures;
LazyLogModule gProfilerLog("prof");
#if defined(GP_OS_android)
class GeckoJavaSampler : public java::GeckoJavaSampler::Natives<GeckoJavaSampler>
{
private:
GeckoJavaSampler();
@@ -579,60 +580,16 @@ uint32_t ActivePS::sNextGeneration = 0;
#undef PS_GET
#undef PS_GET_LOCKLESS
#undef PS_GET_AND_SET
// The mutex that guards accesses to CorePS and ActivePS.
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);
// Each live thread has a ThreadInfo, and we store a reference to it in TLS.
// This class encapsulates that TLS.
class TLSInfo
{
public:
static bool Init(PSLockRef)
@@ -3048,27 +3005,16 @@ profiler_feature_active(uint32_t aFeatur
// This function runs both on and off the main thread.
MOZ_RELEASE_ASSERT(CorePS::Exists());
// This function is hot enough that we use RacyFeatures, not ActivePS.
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
profiler_register_thread(const char* aName, void* aGuessStackTop)
{
DEBUG_LOG("profiler_register_thread(%s)", aName);
MOZ_ASSERT_IF(NS_IsMainThread(), Scheduler::IsCooperativeThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
--- a/tools/profiler/public/GeckoProfiler.h
+++ b/tools/profiler/public/GeckoProfiler.h
@@ -137,16 +137,74 @@ struct ProfilerFeature
static void Clear##Name_(uint32_t& aFeatures) { aFeatures &= ~Name_; }
// Define a bitfield constant, a getter, and two setters for each feature.
PROFILER_FOR_EACH_FEATURE(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
//---------------------------------------------------------------------------
#if !defined(ARCH_ARMV6)
# define PROFILER_DEFAULT_ENTRIES 1000000
#else
# define PROFILER_DEFAULT_ENTRIES 100000
@@ -258,17 +316,24 @@ void profiler_clear_js_context();
// }
//
// where PROFILER_OPERATION is a no-op if the profiler is inactive. In this
// case the profiler_is_active() check is just an optimization -- it prevents
// us calling CreateExpensiveData() unnecessarily in most cases, but the
// expensive data will end up being created but not used if another thread
// stops the profiler between the CreateExpensiveData() and PROFILER_OPERATION
// 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.
bool profiler_is_paused();
// Is the current thread sleeping?
bool profiler_thread_is_sleeping();
// Get all the features supported by the profiler that are accepted by