--- a/tools/profiler/core/platform-linux-android.cpp
+++ b/tools/profiler/core/platform-linux-android.cpp
@@ -260,18 +260,16 @@ SamplerThread::SamplerThread(PSLockRef a
: mActivityGeneration(aActivityGeneration)
, mIntervalMicroseconds(
std::max(1, int(floor(aIntervalMilliseconds * 1000 + 0.5))))
, mMyPid(getpid())
// We don't know what the sampler thread's ID will be until it runs, so set
// mSamplerTid to a dummy value and fill it in for real in ThreadEntry().
, mSamplerTid(-1)
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
-
#if defined(USE_EHABI_STACKWALK)
mozilla::EHABIStackWalkInit();
#elif defined(USE_LUL_STACKWALK)
bool createdLUL = false;
lul::LUL* lul = CorePS::Lul(aLock);
if (!lul) {
lul = new lul::LUL(logging_sink_for_LUL);
CorePS::SetLul(aLock, lul);
@@ -316,18 +314,16 @@ SamplerThread::SamplerThread(PSLockRef a
SamplerThread::~SamplerThread()
{
pthread_join(mThread, nullptr);
}
void
SamplerThread::Stop(PSLockRef aLock)
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
-
// Restore old signal handler. This is global state so it's important that
// we do it now, while gPSMutex is locked. It's safe to do this now even
// though this SamplerThread is still alive, because the next time the main
// loop of Run() iterates it won't get past the mActivityGeneration check,
// and so won't send any signals.
sigaction(SIGPROF, &mOldSigprofHandler, 0);
}
@@ -458,34 +454,30 @@ SamplerThread::SuspendAndSampleAndResume
//
// Unfortunately all this is only doable on non-Android because Bionic doesn't
// have pthread_atfork.
// In the parent, before the fork, record IsPaused, and then pause.
static void
paf_prepare()
{
- // This function can run off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (ActivePS::Exists(lock)) {
ActivePS::SetWasPaused(lock, ActivePS::IsPaused(lock));
ActivePS::SetIsPaused(lock, true);
}
}
// In the parent, after the fork, return IsPaused to the pre-fork state.
static void
paf_parent()
{
- // This function can run off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (ActivePS::Exists(lock)) {
ActivePS::SetIsPaused(lock, ActivePS::WasPaused(lock));
ActivePS::SetWasPaused(lock, false);
}
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -111,16 +111,19 @@ typedef const PSAutoLock& PSLockRef;
#define PS_GET(type_, name_) \
static type_ name_(PSLockRef) { return sInstance->m##name_; } \
#define PS_GET_AND_SET(type_, name_) \
PS_GET(type_, name_) \
static void Set##name_(PSLockRef, type_ a##name_) \
{ sInstance->m##name_ = a##name_; }
+// All functions in this file can run on multiple threads unless they have an
+// NS_IsMainThread() assertion.
+
// This class contains the profiler's core global state, i.e. that which is
// valid even when the profiler is not active. Most profile operations can't do
// anything useful when this class is not instantiated, so we release-assert
// its non-nullness in all such operations.
//
// Accesses to CorePS 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
@@ -323,18 +326,16 @@ private:
IOInterposer::Unregister(IOInterposeObserver::OpAll, observer);
}));
}
}
}
bool ThreadSelected(const char* aThreadName)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(sInstance);
if (mFilters.empty()) {
return true;
}
std::string name = aThreadName;
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
@@ -378,18 +379,16 @@ public:
n += sInstance->mBuffer->SizeOfIncludingThis(aMallocSizeOf);
return n;
}
static bool ShouldProfileThread(PSLockRef aLock, ThreadInfo* aInfo)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(sInstance);
return ((aInfo->IsMainThread() || FeatureThreads(aLock)) &&
sInstance->ThreadSelected(aInfo->Name()));
}
PS_GET(uint32_t, Generation)
@@ -1377,17 +1376,16 @@ StreamNameAndThreadId(JSONWriter& aWrite
aWriter.EndObject();
}
#endif
static void
StreamTaskTracer(PSLockRef aLock, SpliceableJSONWriter& aWriter)
{
#ifdef MOZ_TASK_TRACER
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
aWriter.StartArrayProperty("data");
{
UniquePtr<nsTArray<nsCString>> data =
mozilla::tasktracer::GetLoggedData(CorePS::ProcessStartTime(aLock));
for (uint32_t i = 0; i < data->Length(); ++i) {
aWriter.StringElement((data->ElementAt(i)).get());
@@ -1561,17 +1559,16 @@ BuildJavaThreadJSObject(SpliceableJSONWr
static void
locked_profiler_stream_json_for_this_process(PSLockRef aLock,
SpliceableJSONWriter& aWriter,
double aSinceTime)
{
LOG("locked_profiler_stream_json_for_this_process");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
// Put shared library info
aWriter.StartArrayProperty("libs");
AppendSharedLibraries(aWriter);
aWriter.EndArray();
// Put meta data
@@ -1626,17 +1623,16 @@ locked_profiler_stream_json_for_this_pro
aWriter.EndArray();
}
bool
profiler_stream_json_for_this_process(SpliceableJSONWriter& aWriter, double aSinceTime)
{
LOG("profiler_stream_json_for_this_process");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return false;
}
@@ -1949,18 +1945,16 @@ GeckoProfilerReporter::CollectReports(ns
NS_IMPL_ISUPPORTS(GeckoProfilerReporter, nsIMemoryReporter)
// Find the ThreadInfo for the current thread. This should only be called in
// places where TLSInfo can't be used. On success, *aIndexOut is set to the
// index if it is non-null.
static ThreadInfo*
FindLiveThreadInfo(PSLockRef aLock, int* aIndexOut = nullptr)
{
- // This function runs both on and off the main thread.
-
ThreadInfo* ret = nullptr;
Thread::tid_t id = Thread::GetCurrentId();
const CorePS::ThreadVector& liveThreads = CorePS::LiveThreads(aLock);
for (uint32_t i = 0; i < liveThreads.size(); i++) {
ThreadInfo* info = liveThreads.at(i);
if (info->ThreadId() == id) {
if (aIndexOut) {
*aIndexOut = i;
@@ -1971,18 +1965,16 @@ FindLiveThreadInfo(PSLockRef aLock, int*
}
return ret;
}
static void
locked_register_thread(PSLockRef aLock, const char* aName, void* stackTop)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
MOZ_RELEASE_ASSERT(!FindLiveThreadInfo(aLock));
if (!TLSInfo::Init(aLock)) {
return;
}
@@ -2188,17 +2180,16 @@ profiler_shutdown()
}
}
UniquePtr<char[]>
profiler_get_profile(double aSinceTime)
{
LOG("profiler_get_profile");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
SpliceableChunkedJSONWriter b;
b.Start(SpliceableJSONWriter::SingleLineStyle);
{
if (!profiler_stream_json_for_this_process(b, aSinceTime)) {
return nullptr;
}
@@ -2212,17 +2203,16 @@ profiler_get_profile(double aSinceTime)
return b.WriteFunc()->CopyData();
}
void
profiler_get_start_params(int* aEntries, double* aInterval, uint32_t* aFeatures,
mozilla::Vector<const char*>* aFilters)
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
if (NS_WARN_IF(!aEntries) || NS_WARN_IF(!aInterval) ||
NS_WARN_IF(!aFeatures) || NS_WARN_IF(!aFilters)) {
return;
}
PSAutoLock lock(gPSMutex);
@@ -2246,17 +2236,16 @@ profiler_get_start_params(int* aEntries,
}
}
static void
locked_profiler_save_profile_to_file(PSLockRef aLock, const char* aFilename)
{
LOG("locked_profiler_save_profile_to_file(%s)", aFilename);
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
std::ofstream stream;
stream.open(aFilename);
if (stream.is_open()) {
SpliceableJSONWriter w(mozilla::MakeUnique<OStreamJSONWriteFunc>(stream));
w.Start(SpliceableJSONWriter::SingleLineStyle);
{
@@ -2273,32 +2262,30 @@ locked_profiler_save_profile_to_file(PSL
}
}
void
profiler_save_profile_to_file(const char* aFilename)
{
LOG("profiler_save_profile_to_file(%s)", aFilename);
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return;
}
locked_profiler_save_profile_to_file(lock, aFilename);
}
uint32_t
profiler_get_available_features()
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
uint32_t features = 0;
#define ADD_FEATURE(n_, str_, Name_) ProfilerFeature::Set##Name_(features);
// Add all the possible features.
PROFILER_FOR_EACH_FEATURE(ADD_FEATURE)
@@ -2322,17 +2309,16 @@ profiler_get_available_features()
void
profiler_get_buffer_info_helper(uint32_t* aCurrentPosition,
uint32_t* aEntries,
uint32_t* aGeneration)
{
// This function is called by profiler_get_buffer_info(), which has already
// zeroed the outparams.
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return;
}
@@ -2360,17 +2346,16 @@ locked_profiler_start(PSLockRef aLock, i
#undef LOG_FEATURE
for (uint32_t i = 0; i < aFilterCount; i++) {
LOG("- threads = %s", aFilters[i]);
}
}
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists() && !ActivePS::Exists(aLock));
// Fall back to the default values if the passed-in values are unreasonable.
int entries = aEntries > 0 ? aEntries : PROFILER_DEFAULT_ENTRIES;
double interval = aInterval > 0 ? aInterval : PROFILER_DEFAULT_INTERVAL;
ActivePS::Create(aLock, entries, interval, aFeatures, aFilters, aFilterCount);
@@ -2417,17 +2402,16 @@ locked_profiler_start(PSLockRef aLock, i
}
void
profiler_start(int aEntries, double aInterval, uint32_t aFeatures,
const char** aFilters, uint32_t aFilterCount)
{
LOG("profiler_start");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
SamplerThread* samplerThread = nullptr;
{
PSAutoLock lock(gPSMutex);
// Initialize if necessary.
if (!CorePS::Exists()) {
profiler_init(nullptr);
@@ -2452,17 +2436,16 @@ profiler_start(int aEntries, double aInt
aFilters, aFilterCount);
}
static MOZ_MUST_USE SamplerThread*
locked_profiler_stop(PSLockRef aLock)
{
LOG("locked_profiler_stop");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists() && ActivePS::Exists(aLock));
#ifdef MOZ_TASK_TRACER
if (ActivePS::FeatureTaskTracer(aLock)) {
mozilla::tasktracer::StopLogging();
}
#endif
@@ -2500,17 +2483,16 @@ locked_profiler_stop(PSLockRef aLock)
return samplerThread;
}
void
profiler_stop()
{
LOG("profiler_stop");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
SamplerThread* samplerThread;
{
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return;
@@ -2536,34 +2518,32 @@ profiler_stop()
// in a way that's safe with respect to other gPSMutex-locking operations
// that may have occurred in the meantime.
delete samplerThread;
}
bool
profiler_is_paused()
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return false;
}
return ActivePS::IsPaused(lock);
}
void
profiler_pause()
{
LOG("profiler_pause");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
{
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return;
}
@@ -2575,17 +2555,16 @@ profiler_pause()
NotifyObservers("profiler-paused");
}
void
profiler_resume()
{
LOG("profiler_resume");
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
{
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock)) {
return;
}
@@ -2721,49 +2700,45 @@ profiler_thread_is_sleeping()
return false;
}
return racyInfo->IsSleeping();
}
void
profiler_js_interrupt_callback()
{
- // This function runs both on and off the main thread, on JS threads being
- // sampled.
+ // This function runs on JS threads being sampled.
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
ThreadInfo* info = TLSInfo::Info(lock);
if (!info) {
return;
}
info->PollJSSampling();
}
double
profiler_time()
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
mozilla::TimeDuration delta =
mozilla::TimeStamp::Now() - CorePS::ProcessStartTime(lock);
return delta.ToMilliseconds();
}
UniqueProfilerBacktrace
profiler_get_backtrace()
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock) || ActivePS::FeaturePrivacy(lock)) {
return nullptr;
}
@@ -2803,17 +2778,16 @@ ProfilerBacktraceDestructor::operator()(
}
// Fill the output buffer with the following pattern:
// "Label 1" "\0" "Label 2" "\0" ... "Label N" "\0" "\0"
// TODO: use the unwinder instead of pseudo stack.
void
profiler_get_backtrace_noalloc(char *output, size_t outputSize)
{
- MOZ_RELEASE_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(CorePS::Exists());
MOZ_ASSERT(outputSize >= 2);
char *bound = output + outputSize - 2;
output[0] = output[1] = '\0';
PSAutoLock lock(gPSMutex);
@@ -2862,18 +2836,16 @@ profiler_get_backtrace_noalloc(char *out
*output = '\0';
}
}
static void
locked_profiler_add_marker(PSLockRef aLock, const char* aMarker,
ProfilerMarkerPayload* aPayload)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
MOZ_RELEASE_ASSERT(ActivePS::Exists(aLock) &&
!ActivePS::FeaturePrivacy(aLock));
// aPayload must be freed if we return early.
mozilla::UniquePtr<ProfilerMarkerPayload> payload(aPayload);
RacyThreadInfo* racyInfo = TLSInfo::RacyInfo();
@@ -2887,18 +2859,16 @@ locked_profiler_add_marker(PSLockRef aLo
mozilla::TimeDuration delta = origin - CorePS::ProcessStartTime(aLock);
racyInfo->AddPendingMarker(aMarker, payload.release(),
delta.ToMilliseconds());
}
void
profiler_add_marker(const char* aMarker, ProfilerMarkerPayload* aPayload)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
// aPayload must be freed if we return early.
mozilla::UniquePtr<ProfilerMarkerPayload> payload(aPayload);
if (!ActivePS::Exists(lock) || ActivePS::FeaturePrivacy(lock)) {
@@ -2906,87 +2876,75 @@ profiler_add_marker(const char* aMarker,
}
locked_profiler_add_marker(lock, aMarker, payload.release());
}
void
profiler_tracing(const char* aCategory, const char* aInfo, TracingKind aKind)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock) || ActivePS::FeaturePrivacy(lock)) {
return;
}
auto marker = new ProfilerMarkerTracing(aCategory, aKind);
locked_profiler_add_marker(lock, aInfo, marker);
}
void
profiler_tracing(const char* aCategory, const char* aInfo,
UniqueProfilerBacktrace aCause, TracingKind aKind)
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
if (!ActivePS::Exists(lock) || ActivePS::FeaturePrivacy(lock)) {
return;
}
auto marker =
new ProfilerMarkerTracing(aCategory, aKind, mozilla::Move(aCause));
locked_profiler_add_marker(lock, aInfo, marker);
}
void
profiler_log(const char* aStr)
{
- // This function runs both on and off the main thread.
-
profiler_tracing("log", aStr);
}
PseudoStack*
profiler_get_pseudo_stack()
{
- // This function runs both on and off the main thread.
-
return TLSInfo::Stack();
}
void
profiler_set_js_context(JSContext* aCx)
{
- // This function runs both on and off the main thread.
-
MOZ_ASSERT(aCx);
PSAutoLock lock(gPSMutex);
ThreadInfo* info = TLSInfo::Info(lock);
if (!info) {
return;
}
info->SetJSContext(aCx);
}
void
profiler_clear_js_context()
{
- // This function runs both on and off the main thread.
-
MOZ_RELEASE_ASSERT(CorePS::Exists());
PSAutoLock lock(gPSMutex);
ThreadInfo* info = TLSInfo::Info(lock);
if (!info || !info->mContext) {
return;
}