Empty merge ab/12770256 into aosp-main-future Merged-In: Id8e38b36dd587f2a2a4176f1aea0259b6d02b3f0 Change-Id: I78201b5264fb756e762f21829530f5f5d4554752
diff --git a/OWNERS b/OWNERS index 4f31bde..0d1ae30 100644 --- a/OWNERS +++ b/OWNERS
@@ -1,3 +1,4 @@ cferris@google.com enh@google.com chiahungduan@google.com +include platform/system/core:/janitors/OWNERS #{LAST_RESORT_SUGGESTION}
diff --git a/standalone/allocator_config_wrapper.h b/standalone/allocator_config_wrapper.h index 5477236..ea12a5b 100644 --- a/standalone/allocator_config_wrapper.h +++ b/standalone/allocator_config_wrapper.h
@@ -12,35 +12,7 @@ #include "condition_variable.h" #include "internal_defs.h" #include "secondary.h" - -namespace { - -template <typename T> struct removeConst { - using type = T; -}; -template <typename T> struct removeConst<const T> { - using type = T; -}; - -// This is only used for SFINAE when detecting if a type is defined. -template <typename T> struct voidAdaptor { - using type = void; -}; - -// This is used for detecting the case that defines the flag with wrong type and -// it'll be viewed as undefined optional flag. -template <typename L, typename R> struct assertSameType { - template <typename, typename> struct isSame { - static constexpr bool value = false; - }; - template <typename T> struct isSame<T, T> { - static constexpr bool value = true; - }; - static_assert(isSame<L, R>::value, "Flag type mismatches"); - using type = R; -}; - -} // namespace +#include "type_traits.h" namespace scudo {
diff --git a/standalone/list.h b/standalone/list.h index c6bd32a..e0b8278 100644 --- a/standalone/list.h +++ b/standalone/list.h
@@ -10,17 +10,7 @@ #define SCUDO_LIST_H_ #include "internal_defs.h" - -// TODO: Move the helpers to a header. -namespace { -template <typename T> struct isPointer { - static constexpr bool value = false; -}; - -template <typename T> struct isPointer<T *> { - static constexpr bool value = true; -}; -} // namespace +#include "type_traits.h" namespace scudo { @@ -58,10 +48,11 @@ template <class T> class LinkOp<T, /*LinkWithPtr=*/false> { public: - using LinkTy = decltype(T::Next); + using LinkTy = typename assertSameType< + typename removeConst<decltype(T::Next)>::type, + typename removeConst<decltype(T::EndOfListVal)>::type>::type; LinkOp() = default; - // TODO: Check if the `BaseSize` can fit in `Size`. LinkOp(T *BaseT, uptr BaseSize) : Base(BaseT), Size(static_cast<LinkTy>(BaseSize)) {} void init(T *LinkBase, uptr BaseSize) { @@ -80,11 +71,12 @@ } // Set `X->Next` to `Next`. void setNext(T *X, T *Next) const { - // TODO: Check if the offset fits in the size of `LinkTy`. - if (Next == nullptr) + if (Next == nullptr) { X->Next = getEndOfListVal(); - else + } else { + assertElementInRange(Next); X->Next = static_cast<LinkTy>(Next - Base); + } } T *getPrev(T *X) const { @@ -96,17 +88,22 @@ } // Set `X->Prev` to `Prev`. void setPrev(T *X, T *Prev) const { - DCHECK_LT(reinterpret_cast<uptr>(Prev), - reinterpret_cast<uptr>(Base + Size)); - if (Prev == nullptr) + if (Prev == nullptr) { X->Prev = getEndOfListVal(); - else + } else { + assertElementInRange(Prev); X->Prev = static_cast<LinkTy>(Prev - Base); + } } - // TODO: `LinkTy` should be the same as decltype(T::EndOfListVal). LinkTy getEndOfListVal() const { return T::EndOfListVal; } +private: + void assertElementInRange(T *X) const { + DCHECK_GE(reinterpret_cast<uptr>(X), reinterpret_cast<uptr>(Base)); + DCHECK_LE(static_cast<LinkTy>(X - Base), Size); + } + protected: T *Base = nullptr; LinkTy Size = 0;
diff --git a/standalone/primary32.h b/standalone/primary32.h index 654b129..596c48f 100644 --- a/standalone/primary32.h +++ b/standalone/primary32.h
@@ -387,7 +387,7 @@ struct ReleaseToOsInfo { uptr BytesInFreeListAtLastCheckpoint; - uptr RangesReleased; + uptr NumReleasesAttempted; uptr LastReleasedBytes; u64 LastReleaseAtNs; }; @@ -880,14 +880,14 @@ BytesInFreeList - Sci->ReleaseInfo.BytesInFreeListAtLastCheckpoint; } const uptr AvailableChunks = Sci->AllocatedUser / BlockSize; - Str->append(" %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu " - "inuse: %6zu avail: %6zu releases: %6zu last released: %6zuK " - "latest pushed bytes: %6zuK\n", - ClassId, getSizeByClassId(ClassId), Sci->AllocatedUser >> 10, - Sci->FreeListInfo.PoppedBlocks, Sci->FreeListInfo.PushedBlocks, - InUse, AvailableChunks, Sci->ReleaseInfo.RangesReleased, - Sci->ReleaseInfo.LastReleasedBytes >> 10, - PushedBytesDelta >> 10); + Str->append( + " %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu " + "inuse: %6zu avail: %6zu releases attempted: %6zu last released: %6zuK " + "latest pushed bytes: %6zuK\n", + ClassId, getSizeByClassId(ClassId), Sci->AllocatedUser >> 10, + Sci->FreeListInfo.PoppedBlocks, Sci->FreeListInfo.PushedBlocks, InUse, + AvailableChunks, Sci->ReleaseInfo.NumReleasesAttempted, + Sci->ReleaseInfo.LastReleasedBytes >> 10, PushedBytesDelta >> 10); } void getSizeClassFragmentationInfo(SizeClassInfo *Sci, uptr ClassId, @@ -972,6 +972,10 @@ const uptr Base = First * RegionSize; const uptr NumberOfRegions = Last - First + 1U; + // The following steps contribute to the majority time spent in page + // releasing thus we increment the counter here. + ++Sci->ReleaseInfo.NumReleasesAttempted; + // ==================================================================== // // 2. Mark the free blocks and we can tell which pages are in-use by // querying `PageReleaseContext`. @@ -991,9 +995,8 @@ }; releaseFreeMemoryToOS(Context, Recorder, SkipRegion); - if (Recorder.getReleasedRangesCount() > 0) { + if (Recorder.getReleasedBytes() > 0) { Sci->ReleaseInfo.BytesInFreeListAtLastCheckpoint = BytesInFreeList; - Sci->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount(); Sci->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes(); TotalReleasedBytes += Sci->ReleaseInfo.LastReleasedBytes; }
diff --git a/standalone/primary64.h b/standalone/primary64.h index e382e01..2b520ce 100644 --- a/standalone/primary64.h +++ b/standalone/primary64.h
@@ -530,7 +530,7 @@ struct ReleaseToOsInfo { uptr BytesInFreeListAtLastCheckpoint; - uptr RangesReleased; + uptr NumReleasesAttempted; uptr LastReleasedBytes; // The minimum size of pushed blocks to trigger page release. uptr TryReleaseThreshold; @@ -1144,11 +1144,12 @@ Str->append( "%s %02zu (%6zu): mapped: %6zuK popped: %7zu pushed: %7zu " "inuse: %6zu total: %6zu releases: %6zu last " - "released: %6zuK latest pushed bytes: %6zuK region: 0x%zx (0x%zx)\n", + "releases attempted: %6zuK latest pushed bytes: %6zuK region: 0x%zx " + "(0x%zx)\n", Region->Exhausted ? "E" : " ", ClassId, getSizeByClassId(ClassId), Region->MemMapInfo.MappedUser >> 10, Region->FreeListInfo.PoppedBlocks, Region->FreeListInfo.PushedBlocks, InUseBlocks, TotalChunks, - Region->ReleaseInfo.RangesReleased, + Region->ReleaseInfo.NumReleasesAttempted, Region->ReleaseInfo.LastReleasedBytes >> 10, RegionPushedBytesDelta >> 10, Region->RegionBeg, getRegionBaseByClassId(ClassId)); @@ -1322,7 +1323,7 @@ Context.getReleaseOffset()); auto SkipRegion = [](UNUSED uptr RegionIndex) { return false; }; releaseFreeMemoryToOS(Context, Recorder, SkipRegion); - if (Recorder.getReleasedRangesCount() > 0) { + if (Recorder.getReleasedBytes() > 0) { // This is the case that we didn't hit the release threshold but it has // been past a certain period of time. Thus we try to release some pages // and if it does release some additional pages, it's hint that we are @@ -1342,7 +1343,6 @@ } Region->ReleaseInfo.BytesInFreeListAtLastCheckpoint = BytesInFreeList; - Region->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount(); Region->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes(); } Region->ReleaseInfo.LastReleaseAtNs = getMonotonicTimeFast();
diff --git a/standalone/release.h b/standalone/release.h index 6353daf..7a4912e 100644 --- a/standalone/release.h +++ b/standalone/release.h
@@ -22,8 +22,6 @@ RegionReleaseRecorder(MemMapT *RegionMemMap, uptr Base, uptr Offset = 0) : RegionMemMap(RegionMemMap), Base(Base), Offset(Offset) {} - uptr getReleasedRangesCount() const { return ReleasedRangesCount; } - uptr getReleasedBytes() const { return ReleasedBytes; } uptr getBase() const { return Base; } @@ -33,12 +31,10 @@ void releasePageRangeToOS(uptr From, uptr To) { const uptr Size = To - From; RegionMemMap->releasePagesToOS(getBase() + Offset + From, Size); - ReleasedRangesCount++; ReleasedBytes += Size; } private: - uptr ReleasedRangesCount = 0; uptr ReleasedBytes = 0; MemMapT *RegionMemMap = nullptr; uptr Base = 0; @@ -52,8 +48,6 @@ ReleaseRecorder(uptr Base, uptr Offset = 0, MapPlatformData *Data = nullptr) : Base(Base), Offset(Offset), Data(Data) {} - uptr getReleasedRangesCount() const { return ReleasedRangesCount; } - uptr getReleasedBytes() const { return ReleasedBytes; } uptr getBase() const { return Base; } @@ -62,12 +56,10 @@ void releasePageRangeToOS(uptr From, uptr To) { const uptr Size = To - From; releasePagesToOS(Base, From + Offset, Size, Data); - ReleasedRangesCount++; ReleasedBytes += Size; } private: - uptr ReleasedRangesCount = 0; uptr ReleasedBytes = 0; // The starting address to release. Note that we may want to combine (Base + // Offset) as a new Base. However, the Base is retrieved from
diff --git a/standalone/type_traits.h b/standalone/type_traits.h new file mode 100644 index 0000000..16ed5a0 --- /dev/null +++ b/standalone/type_traits.h
@@ -0,0 +1,47 @@ +//===-- type_traits.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_TYPE_TRAITS_H_ +#define SCUDO_TYPE_TRAITS_H_ + +namespace scudo { + +template <typename T> struct removeConst { + using type = T; +}; +template <typename T> struct removeConst<const T> { + using type = T; +}; + +// This is only used for SFINAE when detecting if a type is defined. +template <typename T> struct voidAdaptor { + using type = void; +}; + +template <typename L, typename R> struct assertSameType { + template <typename, typename> struct isSame { + static constexpr bool value = false; + }; + template <typename T> struct isSame<T, T> { + static constexpr bool value = true; + }; + static_assert(isSame<L, R>::value, "Type mismatches"); + using type = R; +}; + +template <typename T> struct isPointer { + static constexpr bool value = false; +}; + +template <typename T> struct isPointer<T *> { + static constexpr bool value = true; +}; + +} // namespace scudo + +#endif // SCUDO_TYPE_TRAITS_H_