Skip to content

Commit

Permalink
[scudo] Calling getStats requires holding lock
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ChiaHungDuan committed Feb 13, 2023
1 parent f28c1a9 commit 70758b8
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 10 deletions.
4 changes: 0 additions & 4 deletions compiler-rt/lib/scudo/standalone/combined.h
Expand Up @@ -726,9 +726,7 @@ class Allocator {
// 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) {
Expand All @@ -740,9 +738,7 @@ class Allocator {

void printStats() {
ScopedString Str;
disable();
getStats(&Str);
enable();
Str.output();
}

Expand Down
6 changes: 5 additions & 1 deletion compiler-rt/lib/scudo/standalone/primary32.h
Expand Up @@ -230,15 +230,19 @@ template <typename Config> class SizeClassAllocator32 {
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;
}
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) {
Expand Down
12 changes: 10 additions & 2 deletions compiler-rt/lib/scudo/standalone/primary64.h
Expand Up @@ -199,6 +199,7 @@ template <typename Config> class SizeClassAllocator64 {
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;
Expand All @@ -209,8 +210,11 @@ template <typename Config> class SizeClassAllocator64 {
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) {
Expand Down Expand Up @@ -577,7 +581,11 @@ template <typename Config> class SizeClassAllocator64 {
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);
Expand Down
3 changes: 2 additions & 1 deletion compiler-rt/lib/scudo/standalone/quarantine.h
Expand Up @@ -215,7 +215,8 @@ template <typename Callback, typename Node> class GlobalQuarantine {
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",
Expand Down
5 changes: 3 additions & 2 deletions compiler-rt/lib/scudo/standalone/secondary.h
Expand Up @@ -438,7 +438,7 @@ template <typename Config> class MapAllocator {
return getBlockEnd(Ptr) - reinterpret_cast<uptr>(Ptr);
}

void getStats(ScopedString *Str) const;
void getStats(ScopedString *Str);

void disable() {
Mutex.lock();
Expand Down Expand Up @@ -615,7 +615,8 @@ void MapAllocator<Config>::deallocate(Options Options, void *Ptr) {
}

template <typename Config>
void MapAllocator<Config>::getStats(ScopedString *Str) const {
void MapAllocator<Config>::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,
Expand Down

0 comments on commit 70758b8

Please sign in to comment.