commit c393a4ee5cfffd2882223d2f98c2527ae60f8d0f
parent db8adc0130c65d56868800a68a50c63c77bd5e5e
Author: Paul Bone <paul@bone.id.au>
Date: Tue, 18 Nov 2025 02:07:23 +0000
Bug 1987055 - pt 2. Merge purge results, ReachedThreshold and Busy r=glandium,profiler-reviewers,mstange
Differential Revision: https://phabricator.services.mozilla.com/D263335
Diffstat:
3 files changed, 14 insertions(+), 17 deletions(-)
diff --git a/memory/build/mozjemalloc.cpp b/memory/build/mozjemalloc.cpp
@@ -1897,7 +1897,7 @@ ArenaPurgeResult arena_t::Purge(PurgeCondition aCond, PurgeStats& aStats) {
if (!ShouldContinuePurge(aCond)) {
mIsPurgePending = false;
- return ReachedThreshold;
+ return ReachedThresholdOrBusy;
}
// Take a single chunk and attempt to purge some of its dirty pages. The
@@ -1920,16 +1920,17 @@ ArenaPurgeResult arena_t::Purge(PurgeCondition aCond, PurgeStats& aStats) {
chunk = mChunksDirty.Last();
}
if (!chunk) {
- // There are chunks with dirty pages (because mNumDirty > 0 above) but
- // they're not in mChunksDirty. That can happen if they're busy being
- // purged by other threads.
// We have to clear the flag to preserve the invariant that if Purge()
// returns anything other than NotDone then the flag is clear. If there's
// more purging work to do in other chunks then either other calls to
// Purge() (in other threads) will handle it or we rely on
// ShouldStartPurge() returning true at some point in the future.
mIsPurgePending = false;
- return Busy;
+
+ // There are chunks with dirty pages (because mNumDirty > 0 above) but
+ // they're not in mChunksDirty, they might not have enough dirty pages.
+ // Or maybe they're busy being purged by other threads.
+ return ReachedThresholdOrBusy;
}
MOZ_ASSERT(chunk->mNumDirty > 0);
@@ -1984,7 +1985,7 @@ ArenaPurgeResult arena_t::Purge(PurgeCondition aCond, PurgeStats& aStats) {
}
// There's nothing else to do here, our caller may execute Purge() again
// if continue_purge_arena is true.
- return continue_purge_arena ? NotDone : ReachedThreshold;
+ return continue_purge_arena ? NotDone : ReachedThresholdOrBusy;
}
#ifdef MALLOC_DECOMMIT
@@ -2033,7 +2034,7 @@ ArenaPurgeResult arena_t::Purge(PurgeCondition aCond, PurgeStats& aStats) {
purged_once = true;
}
- return continue_purge_arena ? NotDone : ReachedThreshold;
+ return continue_purge_arena ? NotDone : ReachedThresholdOrBusy;
}
ArenaPurgeResult arena_t::PurgeLoop(PurgeCondition aCond, const char* aCaller,
diff --git a/memory/build/mozjemalloc_types.h b/memory/build/mozjemalloc_types.h
@@ -222,15 +222,14 @@ static inline bool jemalloc_ptr_is_freed_page(jemalloc_ptr_info_t* info) {
// The result of purging memory from a sigle arena
enum ArenaPurgeResult {
- // The stop threshold of dirty pages was reached.
- ReachedThreshold,
+ // The stop threshold of dirty pages was reached or all the remaining chunks
+ // that may have dirty pages are busy. The allocator can't always tell the
+ // difference between these conditions.
+ ReachedThresholdOrBusy,
// There's more chunks in this arena that could be purged.
NotDone,
- // The only chunks with dirty pages are busy being purged by other threads.
- Busy,
-
// The arena needs to be destroyed by the caller.
Dying,
};
diff --git a/tools/profiler/core/memory_markers.cpp b/tools/profiler/core/memory_markers.cpp
@@ -68,15 +68,12 @@ class GeckoProfilerMallocCallbacks : public MallocProfilerCallbacks {
ArenaPurgeResult aResult) override {
const char* result = nullptr;
switch (aResult) {
- case ReachedThreshold:
- result = "Reached dirty page threshold";
+ case ReachedThresholdOrBusy:
+ result = "Can't find enough dirty memory to purge";
break;
case NotDone:
result = "Purge exited early (eg caller set a time budget)";
break;
- case Busy:
- result = "Last chunk is busy being purged on another thread";
- break;
case Dying:
result = "Arena is being destroyed";
break;