diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 985bfb49884d1..c9ba28a52f780 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -25,6 +25,7 @@ #include "size_class_allocator.h" #include "stack_depot.h" #include "string_utils.h" +#include "tracing.h" #include "tsd.h" #include "scudo/interface.h" @@ -671,10 +672,11 @@ class Allocator { void releaseToOS(ReleaseToOS ReleaseType) { initThreadMaybe(); + SCUDO_SCOPED_TRACE(GetReleaseToOSTraceName(ReleaseType)); if (ReleaseType == ReleaseToOS::ForceAll) drainCaches(); Primary.releaseToOS(ReleaseType); - Secondary.releaseToOS(); + Secondary.releaseToOS(ReleaseType); } // Iterate over all chunks and call a callback for all busy chunks located diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h index e2de50b93adc3..49aa74adfc10a 100644 --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -511,6 +511,8 @@ uptr SizeClassAllocator32::tryReleaseToOS(uptr ClassId, template uptr SizeClassAllocator32::releaseToOS(ReleaseToOS ReleaseType) { + SCUDO_SCOPED_TRACE(GetPrimaryReleaseToOSTraceName(ReleaseType)); + uptr TotalReleasedBytes = 0; for (uptr I = 0; I < NumClasses; I++) { if (I == SizeClassMap::BatchClassId) @@ -1056,6 +1058,8 @@ uptr SizeClassAllocator32::releaseToOSMaybe(SizeClassInfo *Sci, uptr ClassId, ReleaseToOS ReleaseType) REQUIRES(Sci->Mutex) { + SCUDO_SCOPED_TRACE(GetPrimaryReleaseToOSMaybeTraceName(ReleaseType)); + const uptr BlockSize = getSizeByClassId(ClassId); DCHECK_GE(Sci->FreeListInfo.PoppedBlocks, Sci->FreeListInfo.PushedBlocks); diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h index 3cb040c514eda..7727049426b47 100644 --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -22,6 +22,7 @@ #include "stats.h" #include "string_utils.h" #include "thread_annotations.h" +#include "tracing.h" namespace scudo { @@ -1307,6 +1308,8 @@ uptr SizeClassAllocator64::tryReleaseToOS(uptr ClassId, template uptr SizeClassAllocator64::releaseToOS(ReleaseToOS ReleaseType) { + SCUDO_SCOPED_TRACE(GetPrimaryReleaseToOSTraceName(ReleaseType)); + uptr TotalReleasedBytes = 0; for (uptr I = 0; I < NumClasses; I++) { if (I == SizeClassMap::BatchClassId) @@ -1376,6 +1379,8 @@ uptr SizeClassAllocator64::releaseToOSMaybe(RegionInfo *Region, uptr ClassId, ReleaseToOS ReleaseType) REQUIRES(Region->MMLock) EXCLUDES(Region->FLLock) { + SCUDO_SCOPED_TRACE(GetPrimaryReleaseToOSMaybeTraceName(ReleaseType)); + const uptr BlockSize = getSizeByClassId(ClassId); uptr BytesInFreeList; const uptr AllocatedUserEnd = diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h index 38c9a9e6e2d70..f0b7bceb010f0 100644 --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -19,6 +19,7 @@ #include "stats.h" #include "string_utils.h" #include "thread_annotations.h" +#include "tracing.h" #include "vector.h" namespace scudo { @@ -118,7 +119,7 @@ template class MapAllocatorNoCache { bool canCache(UNUSED uptr Size) { return false; } void disable() {} void enable() {} - void releaseToOS() {} + void releaseToOS(ReleaseToOS) {} void disableMemoryTagging() {} void unmapTestOnly() {} bool setOption(Option O, UNUSED sptr Value) { @@ -351,6 +352,9 @@ class MapAllocatorCache { // same time will not actually release any extra elements. Therefore, // let any other thread continue, skipping the release. if (Mutex.tryLock()) { + SCUDO_SCOPED_TRACE( + GetSecondaryReleaseToOSTraceName(ReleaseToOS::Normal)); + // TODO: Add ReleaseToOS logic to LRU algorithm releaseOlderThan(Time - static_cast(Interval) * 1000000); Mutex.unlock(); @@ -499,7 +503,9 @@ class MapAllocatorCache { return true; } - void releaseToOS() EXCLUDES(Mutex) { + void releaseToOS([[maybe_unused]] ReleaseToOS ReleaseType) EXCLUDES(Mutex) { + SCUDO_SCOPED_TRACE(GetSecondaryReleaseToOSTraceName(ReleaseType)); + // Since this is a request to release everything, always wait for the // lock so that we guarantee all entries are released after this call. ScopedLock L(Mutex); @@ -574,6 +580,8 @@ class MapAllocatorCache { } void releaseOlderThan(u64 Time) REQUIRES(Mutex) { + SCUDO_SCOPED_TRACE(GetSecondaryReleaseOlderThanTraceName()); + if (!LRUEntries.size() || OldestTime == 0 || OldestTime > Time) return; OldestTime = 0; @@ -669,7 +677,7 @@ template class MapAllocator { bool setOption(Option O, sptr Value) { return Cache.setOption(O, Value); } - void releaseToOS() { Cache.releaseToOS(); } + void releaseToOS(ReleaseToOS ReleaseType) { Cache.releaseToOS(ReleaseType); } void disableMemoryTagging() { Cache.disableMemoryTagging(); } diff --git a/compiler-rt/lib/scudo/standalone/tracing.h b/compiler-rt/lib/scudo/standalone/tracing.h new file mode 100644 index 0000000000000..ac1f746128823 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/tracing.h @@ -0,0 +1,50 @@ +//===-- tracing.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef SCUDO_TRACING_H_ +#define SCUDO_TRACING_H_ + +#if defined(SCUDO_ENABLE_TRACING) + +// This file must include definitions for all of the functions below. +#include "custom_scudo_tracing.h" + +#else + +// Should start a trace in the given scope, and end the trace when going out of +// scope. +#define SCUDO_SCOPED_TRACE(Name) + +// Create a trace name for the call to releaseToOS. +static inline const char *GetReleaseToOSTraceName(scudo::ReleaseToOS) { + return nullptr; +} + +// Create a trace name for the call to releaseToOSMaybe in the primary. +static inline const char * +GetPrimaryReleaseToOSMaybeTraceName(scudo::ReleaseToOS) { + return nullptr; +} + +static inline const char *GetPrimaryReleaseToOSTraceName(scudo::ReleaseToOS) { + return nullptr; +} + +// Create a trace name for the call to releaseToOS in the secondary. +static inline const char *GetSecondaryReleaseToOSTraceName(scudo::ReleaseToOS) { + return nullptr; +} + +// Create a trace name for the call to releaseOlderThan in the secondary. +static inline const char *GetSecondaryReleaseOlderThanTraceName() { + return nullptr; +} + +#endif + +#endif // SCUDO_TRACING_H_