From 70758b801df9b76b8200ae6f22cab44554545693 Mon Sep 17 00:00:00 2001 From: Chia-hung Duan Date: Thu, 19 Jan 2023 17:52:12 +0000 Subject: [PATCH] [scudo] Calling getStats requires holding lock We didn't acquire the mutex while accessing those lock protected data, this CL fixes it and now we don't need to disable the allocator while reading its states. Differential Revision: https://reviews.llvm.org/D142149 --- compiler-rt/lib/scudo/standalone/combined.h | 4 ---- compiler-rt/lib/scudo/standalone/primary32.h | 6 +++++- compiler-rt/lib/scudo/standalone/primary64.h | 12 ++++++++++-- compiler-rt/lib/scudo/standalone/quarantine.h | 3 ++- compiler-rt/lib/scudo/standalone/secondary.h | 5 +++-- 5 files changed, 20 insertions(+), 10 deletions(-) diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index b6d74ab..826e2a0 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -726,9 +726,7 @@ public: // sizing purposes. uptr getStats(char *Buffer, uptr Size) { ScopedString Str; - disable(); const uptr Length = getStats(&Str) + 1; - enable(); if (Length < Size) Size = Length; if (Buffer && Size) { @@ -740,9 +738,7 @@ public: void printStats() { ScopedString Str; - disable(); getStats(&Str); - enable(); Str.output(); } diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h index a3d908c..c9e6c6a 100644 --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -230,6 +230,7 @@ public: uptr PushedBlocks = 0; for (uptr I = 0; I < NumClasses; I++) { SizeClassInfo *Sci = getSizeClassInfo(I); + ScopedLock L(Sci->Mutex); TotalMapped += Sci->AllocatedUser; PoppedBlocks += Sci->Stats.PoppedBlocks; PushedBlocks += Sci->Stats.PushedBlocks; @@ -237,8 +238,11 @@ public: Str->append("Stats: SizeClassAllocator32: %zuM mapped in %zu allocations; " "remains %zu\n", TotalMapped >> 20, PoppedBlocks, PoppedBlocks - PushedBlocks); - for (uptr I = 0; I < NumClasses; I++) + for (uptr I = 0; I < NumClasses; I++) { + SizeClassInfo *Sci = getSizeClassInfo(I); + ScopedLock L(Sci->Mutex); getStats(Str, I, 0); + } } bool setOption(Option O, sptr Value) { diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h index b653bc8..68bf229 100644 --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -199,6 +199,7 @@ public: uptr PushedBlocks = 0; for (uptr I = 0; I < NumClasses; I++) { RegionInfo *Region = getRegionInfo(I); + ScopedLock L(Region->Mutex); if (Region->MappedUser) TotalMapped += Region->MappedUser; PoppedBlocks += Region->Stats.PoppedBlocks; @@ -209,8 +210,11 @@ public: TotalMapped >> 20, 0U, PoppedBlocks, PoppedBlocks - PushedBlocks); - for (uptr I = 0; I < NumClasses; I++) + for (uptr I = 0; I < NumClasses; I++) { + RegionInfo *Region = getRegionInfo(I); + ScopedLock L(Region->Mutex); getStats(Str, I, 0); + } } bool setOption(Option O, sptr Value) { @@ -577,7 +581,11 @@ private: if (!Region->Exhausted) { Region->Exhausted = true; ScopedString Str; - getStats(&Str); + // FIXME: getStats() needs to go over all the regions and + // will take the locks of them. Which means we will try to recursively + // acquire the `Region->Mutex` which is not supported. It will be + // better to log this somewhere else. + // getStats(&Str); Str.append( "Scudo OOM: The process has exhausted %zuM for size class %zu.\n", RegionSize >> 20, Size); diff --git a/compiler-rt/lib/scudo/standalone/quarantine.h b/compiler-rt/lib/scudo/standalone/quarantine.h index 2d231c3..2d240d2 100644 --- a/compiler-rt/lib/scudo/standalone/quarantine.h +++ b/compiler-rt/lib/scudo/standalone/quarantine.h @@ -215,7 +215,8 @@ public: recycle(0, Cb); } - void getStats(ScopedString *Str) const { + void getStats(ScopedString *Str) { + ScopedLock L(CacheMutex); // It assumes that the world is stopped, just as the allocator's printStats. Cache.getStats(Str); Str->append("Quarantine limits: global: %zuK; thread local: %zuK\n", diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h index 2d177576..1c4d0eff 100644 --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -438,7 +438,7 @@ public: return getBlockEnd(Ptr) - reinterpret_cast(Ptr); } - void getStats(ScopedString *Str) const; + void getStats(ScopedString *Str); void disable() { Mutex.lock(); @@ -615,7 +615,8 @@ void MapAllocator::deallocate(Options Options, void *Ptr) { } template -void MapAllocator::getStats(ScopedString *Str) const { +void MapAllocator::getStats(ScopedString *Str) { + ScopedLock L(Mutex); Str->append("Stats: MapAllocator: allocated %u times (%zuK), freed %u times " "(%zuK), remains %u (%zuK) max %zuM\n", NumberOfAllocs, AllocatedBytes >> 10, NumberOfFrees, -- 2.7.4