101 Commits

Author SHA1 Message Date
Christopher Ferris
ef962752d9
[scudo] Allow the quarantine code to be compiled out (#151064)
Add a new configuration option QuarantineDisabled that allows all of the
quarantine code to be compiled out.

Add new tests that verify that the code is removed properly.

On Android, this saves ~4000 bytes for 32 bit and ~6000 bytes for 64
bit.

On Android, I used some microbenchmarks that do malloc/free in a loop
and for allocations in the primary, the performance is about the same
for both 32 bit and 64 bit. For secondary allocations, I saw ~8% speed
up on 32 bit and ~3% on 64 bit speed up which feels like it could just
be code size improvements.
2025-07-30 19:41:14 -07:00
Christopher Ferris
30532c13d2
[scudo] Fix secondary caching for mte (#150156)
The current code always unmaps a secondary allocation when MTE is
enabled. Fix this to match the comment, namely only unmap if MTE was
enabled and is no longer enabled after acquiring the lock.

In addition, allow quaratine to work in the secondary even if MTE is not
enabled.
2025-07-28 12:56:16 -07:00
Christopher Ferris
134cb8877e
[scudo] Use a tryLock in secondary release to OS (#132827)
In the caching part of the secondary path, when about to try to release
memory to the OS, we always wait while acquiring the lock. However, if
multiple threads are attempting this at the same time, all other threads
will likely do nothing when the release call is made. Change the
algorithm to skip the release if there is another release in process.

Also, pull the lock outside the releaseOlderThan function. This is so
that in the store path, we use the tryLock and skip if another thread is
releasing. But in the path where a forced release call is being made,
that call will wait for release to complete which guarantees that all
entries are released when requested.
2025-03-25 16:32:16 -07:00
Christopher Ferris
3d35246c50
[scudo] Make guard pages optional in the secondary (#125960)
Add an optional flag for the secondary allocator called
`EnableGuardPages` to enable/disable the use of guard pages. By default,
this option is enabled.
2025-02-06 17:03:30 -08:00
ChiaHungDuan
9c5217c4ed
[scudo] Use internal list to manage the LRU cache (#117946) 2024-12-04 11:31:41 -08:00
Thurston Dang
ddd1a02048 Revert "[scudo] Update secondary cache time-based release logic (#107507)"
This reverts commit e5271fef8fd8931370f04702ba2f9e8b2ab0e523.

Reason: buildbot breakage: https://lab.llvm.org/buildbot/#/builders/139/builds/3806
2024-09-16 20:43:55 +00:00
Joshua Baehring
e5271fef8f
[scudo] Update secondary cache time-based release logic (#107507)
Secondary cache entries are now released to the OS from least recent to
most recent entries. This helps to avoid unnecessary scans of the cache
since entries ready to be released (specifically, entries that are
considered old relative to the configurable release interval) will
always be at the tail of the list of committed entries by the LRU
ordering. For this same reason, the `OldestTime` variable is no longer
needed to indicate when releases are necessary so it has been removed.
2024-09-16 11:33:03 -07:00
ChiaHungDuan
323911de27
Reapply "[scudo] Fix the logic of MaxAllowedFragmentedPages" (#108130) (#108134)
This reverts commit 76151c449080b7239c8b442291514a4300d51cba.

Also changed to check MaxAllowedFragmentedPages.
2024-09-10 22:24:06 -07:00
ChiaHungDuan
76151c4490
Revert "[scudo] Fix the logic of MaxAllowedFragmentedPages" (#108130)
Reverts llvm/llvm-project#107927

We are supposed to check the MaxAllowedFragmentedPages instead.
2024-09-10 18:56:49 -07:00
ChiaHungDuan
6e854a6a01
[scudo] Fix the logic of MaxAllowedFragmentedPages (#107927)
MTE doesn't support MaxReleasedCachePages which may break the assumption
that only the first 4 pages will have memory tagged.
2024-09-10 17:46:02 -07:00
Joshua Baehring
0ef7b1d21c
[scudo] Update secondary cache released pages bound. (#106466)
`MaxReleasedCachePages` has been set to 4. Initially, in #105009 , we
set `MaxReleasedCachePages` to 0 so that the partial chunk heuristic
could be introduced incrementally as we observed its impact on retrieval
order and more generally, performance.

Co-authored-by: Joshua Baehring <josh.baehring@yale.edu>
2024-09-03 13:56:46 -07:00
Caslyn Tonelli
31204b472e
[scudo] Make comment compatible with gcc (#106137)
gcc interprets a backslash '\\' as the last char before a new line as a
line continuation character, even in a comment context. This can produce
an "error: multi-line comment [-Werror=comment]".

This PR adds delimiters so that the comment can compile with gcc.
2024-08-26 15:29:29 -07:00
Joshua Baehring
643bf6cb01
[scudo] Add partial chunk heuristic to retrieval algorithm. (#105009)
Previously the secondary cache retrieval algorithm would not allow
retrievals of memory chunks where the number of unused bytes would be
greater than than `MaxUnreleasedCachePages * PageSize` bytes. This meant
that even if a memory chunk satisfied the requirements of the optimal
fit algorithm, it may not be returned. This remains true if memory
tagging is enabled. However, if memory tagging is disabled, a new
heuristic has been put in place. Specifically, If a memory chunk is a
non-optimal fit, the cache retrieval algorithm will attempt to release
the excess memory to force a cache hit while keeping RSS down.

In the event that a memory chunk is a non-optimal fit, the retrieval
algorithm will release excess memory as long as the amount of memory to
be released is less than or equal to 4 Pages. If the amount of memory to
be released exceeds 4 Pages, the retrieval algorithm will not consider
that cached memory chunk valid for retrieval.

This change also addresses an alignment issue in a test case submitted
in #104807.
2024-08-26 10:44:39 -07:00
ChiaHungDuan
f9031f00f2
Revert "[scudo] Add partial chunk heuristic to retrieval algorithm." (#104894)
Reverts llvm/llvm-project#104807
2024-08-19 22:25:52 -07:00
Joshua Baehring
27dc247964
[scudo] Add partial chunk heuristic to retrieval algorithm. (#104807)
Previously the secondary cache retrieval algorithm would not allow
retrievals of memory chunks where the number of unused bytes would be
greater than than `MaxUnusedCachePages * PageSize` bytes. This meant
that even if a memory chunk satisfied the requirements of the optimal
fit algorithm, it may not be returned. This remains true if memory
tagging is enabled. However, if memory tagging is disabled, a new
heuristic has been put in place. Specifically, If a memory chunk is a
non-optimal fit, the cache retrieval algorithm will attempt to release
the excess memory to force a cache hit while keeping RSS down.

In the event that a memory chunk is a non-optimal fit, the retrieval
algorithm will release excess memory as long as the amount of memory to
be released is less than or equal to 16 KB. If the amount of memory to
be released exceeds 16 KB, the retrieval algorithm will not consider
that cached memory chunk valid for retrieval.
2024-08-19 18:03:35 -07:00
ChiaHungDuan
fdc4955086
Revert "[scudo] Separated committed and decommitted entries." (#104045)
Reverts llvm/llvm-project#101409

This caused some memory usage regressions and it has a known bug in page
releasing.
2024-08-14 09:09:50 -07:00
Joshua Baehring
9f3ff8d28a
[scudo] Separated committed and decommitted entries. (#101409)
Initially, the LRU list stored all mapped entries with no distinction
between the committed (non-madvise()'d) entries and decommitted
(madvise()'d) entries. Now these two types of entries re separated into
two lists, allowing future cache logic to branch depending on whether or
not entries are committed or decommitted. Furthermore, the retrieval
algorithm will prioritize committed entries over decommitted entries.
Specifically, committed entries that satisfy the MaxUnusedCachePages
requirement are retrieved before optimal-fit, decommitted entries.

This commit addresses the compiler errors raised
[here](https://github.com/llvm/llvm-project/pull/100818#issuecomment-2261043261).
2024-08-09 10:56:07 -07:00
Joshua Baehring
373d35d1e1
[scudo] Added test fixture for cache tests. (#102230)
The test fixture simplifies some of the logic for allocations and
mmap-based allocations
are separated from the cache to allow for more direct cache tests.
Additionally, a couple
of end to end tests for the cache and the LRU algorithm are added.
2024-08-08 13:44:27 -07:00
Christopher Ferris
a753c9921e
[scudo] Die when store is called on MapAllocatorNoCache objects. (#102403) 2024-08-07 18:50:22 -07:00
ChiaHungDuan
e9c9fde3b7
[scudo] Avoid accessing inaccessible pages in unmap() in secondary (#102367) 2024-08-07 15:42:11 -07:00
ChiaHungDuan
dd741fc1b1
[scudo][NFC] Add a default unmap() to unmap all pages (#102234) 2024-08-07 11:50:25 -07:00
Joshua Baehring
2336ef96b3
[scudo] Refactor store() and retrieve(). (#102024)
store() and retrieve() have been refactored so that the scudo headers
are abstracted away from cache operations.
2024-08-06 08:52:19 -07:00
ChiaHungDuan
496fedacca
Revert "[scudo] Separated committed and decommitted entries." (#101375)
Reverts llvm/llvm-project#100818
2024-07-31 11:02:48 -07:00
Joshua Baehring
8b2688bd17
[scudo] Separated committed and decommitted entries. (#100818)
Initially, the LRU list stored all mapped entries with no distinction
between the committed (non-madvise()'d) entries and decommitted
(madvise()'d) entries. Now these two types of entries are separated into
two lists, allowing future cache logic to branch depending on whether or
not entries are committed or decommitted. Furthermore, the retrieval
algorithm will prioritize committed entries over decommitted entries.
Specifically, valid-fit, committed entries (not necessarily optimal-fit)
are retrieved before optimal-fit, decommitted entries.
2024-07-31 09:10:24 -07:00
Thurston Dang
ce811fb6d9
[NFCI][scudo] Remove unused variable 'MaxCount' (#100201)
Fixes "error: unused variable 'MaxCount' [-Werror,-Wunused-variable]",
which is no longer used after
https://github.com/llvm/llvm-project/pull/99409
2024-07-23 14:01:48 -07:00
Joshua Baehring
95ea37cd63
[scudo] Added LRU eviction policy to secondary cache. (#99409)
The logic for emptying the cache now follows an LRU eviction policy.
When the cache is full on any given free operation, the oldest entry in
the cache is evicted, and the memory associated with that cache entry is
unmapped.

Finding empty cache entries is now a constant operation with the use of
a stack of available cache entries.

Through the LRU structure, the cache retrieval algorithm now only
iterates through valid entries of the cache. Furthermore, the retrieval
algorithm will first search cache entries that have not been decommitted
(i.e. madvise() has not been called on their corresponding memory
chunks) to reduce the likelihood of returning a memory chunk to the user
that would induce a page fault.
2024-07-23 11:33:12 -07:00
Joshua Baehring
16aa39ad94
[scudo] Update error handling for seondary cache entry count (#95595)
Initially, the scudo allocator would return an error if the user
attempted to set the cache capacity
(i.e. the number of possible entries in the cache) above the maximum
cache capacity.
Now the allocator will resort to using the maximum cache capacity in
this event.
An error will still be returned if the user attempts to set the number
of entries to a negative value.
2024-06-17 14:06:31 -07:00
ChiaHungDuan
11f4f458d9
[scudo] Support setting default value of ReleaseToOsIntervalMs in config (#90256) 2024-04-29 08:41:46 -07:00
ChiaHungDuan
6b149f70ab
[scudo] Dump ReleaseToOsIntervalMs (#86887)
This can be adjusted during runtime and it may impact the memory
footprint if it's set to a big value or is disabled.
2024-03-28 15:28:01 -07:00
ChiaHungDuan
2dc9ec47fb
[scudo] Refactor allocator config to support optional flags (#81805)
Instead of explicitly disabling a feature by declaring the variable and
set it to false, this change supports the optional flags. I.e., you can
skip certain flags if you are not using it.

This optional feature supports both forms,
  1. Value: A parameter for a feature. E.g., EnableRandomOffset
  2. Type: A C++ type implementing a feature. E.g., ConditionVariableT

On the other hand, to access the flags will be through one of the
wrappers, BaseConfig/PrimaryConfig/SecondaryConfig/CacheConfig
(CacheConfig is embedded in SecondaryConfig). These wrappers have the
getters to access the value and the type. When adding a new feature, we
need to add it to `allocator_config.def` and mark the new variable with
either *_REQUIRED_* or *_OPTIONAL_* macro so that the accessor will be
generated properly.

In addition, also remove the need of `UseConditionVariable` to flip
on/off of condition variable. Now we only need to define the type of
condition variable.
2024-03-13 16:05:24 -07:00
Andrei Homescu
bf0f874e48
[scudo] Avoid splitting aligned allocations on Trusty (#69281)
Don't use multiple tagged pages at the beginning of an allocation, since
it prevents using such allocations for memrefs, and mappings aren't
reused anyway since Trusty uses MapAllocatorNoCache.
Upstreamed from https://r.android.com/2537251.

Co-authored-by: Marco Nelissen <marcone@google.com>
2024-02-29 15:05:47 -08:00
Christopher Ferris
a8ef9c0969
[scudo] Add utilization percentages for stats. (#75101)
Refactor the percentage display in the secondary code. Re-use that to
display a utilization percentage when displaying fragmentation data.
2023-12-11 16:42:44 -08:00
Christopher Ferris
e15fcd7ba4
[scudo] Use the releaseAndZeroPagesToOS function. (#71256)
All of the code assumes that when the pages are released, the entry is
zero'd, so use the correct function. On most systems, this does not
change anything.
2023-11-06 12:46:37 -08:00
ChiaHungDuan
ce00dde80e
[scudo] Mark page status in getStats in secondary (#67588)
Cache entry marked with [R] indicates that the pages have been released
by releaseToOS().
2023-10-03 06:13:32 +08:00
ChiaHungDuan
dc4bf78e4e
Fix the calculation of fragmented bytes in secondary (#66422)
The fragmentation of secondary cache is the difference between mapped
page size and the user request size
2023-09-14 15:24:54 -07:00
Fernando
7a120fcd66 [scudo] Fragmentation info secondary cache
Added a variable that tracks the FragmentedBytes in the secondary cache.
Updates this information after successful retrieves and stores. Dumps
info in getStats().

Reviewed By: Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D157527
2023-08-11 00:06:40 +00:00
Fernando
a7f0195b44 [scudo] secondary allocator cache optimal-fit retrieval
changed cache retrieve algorithm to an "optimal-fit" which immediate
returns blocks that are less than 110% of the requested size. This
reduces memory waste while still allowing for an early return without
traversing the entire array of cached blocks

Reviewed By: cferris, Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D157155
2023-08-08 23:37:31 +00:00
Fernando
12a22ec755 [scudo] Dump MapAllocatorCache::retrieve() data
Keeps track of CallsToRetrieve, how many SuccessfulRetrieves, from
cached block allocations. Dumps this data in the
MapAllocatorCache::getStats() function

Reviewed By: cferris, Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D157154
2023-08-08 01:32:29 +00:00
Chia-hung Duan
aaf11496a6 [scudo] Respect the return value of ReservedMemory::create() (NFC)
Reviewed By: cferris

Differential Revision: https://reviews.llvm.org/D156586
2023-07-31 22:20:19 +00:00
Chia-hung Duan
aeef9c0274 [scudo] CanCache should use Size + HeadersSize instead of RoundedSize
Cached block may have nearly aligned address for a certain alignment so
that we don't have to round up the size in advance. The rounding should
only happen at determing the availability of a cached block.

Reviewed By: cferris

Differential Revision: https://reviews.llvm.org/D156582
2023-07-31 20:10:43 +00:00
Chia-hung Duan
2fcfaeecfb Revert "[scudo] seperate cache retrieval logic"
RoundedSize is supposed to be used on directly mapping. To determine if
a cached block is feasible, the size doesn't need to be rounded in
advance. As a result, the use of RoundedSize may miss some chance of
using cached blocks.

This reverts commit 4c6b8bb87b3452d0bcef83cd0ea712d8426603b8.

Reviewed By: frs513

Differential Revision: https://reviews.llvm.org/D156583
2023-07-31 17:37:55 +00:00
Christopher Ferris
867f2d9e5c [scudo] Make Options a reference for functions.
Modify all places that use the Options structure to be a const
reference. The underlying structure is a u32 so making it a
reference doesn't really do anything. However, if the structure
changes in the future it already works and avoids future coders
wondering why a structure is being passed by value. This also
makes it clear that the Options should not be modified in those functions.

Reviewed By: Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D156372
2023-07-26 18:21:39 -07:00
Fernando
a0b9f1f84b [scudo] set/check invalid cache entries
made checking for invalid cache entries and setting invalid cache
entries more implicit and clear.

Reviewed By: cferris

Differential Revision: https://reviews.llvm.org/D155983
2023-07-25 19:26:32 +00:00
Fernando
4c6b8bb87b [scudo] seperate cache retrieval logic
Split cache::retrieve() into separate functions. One that retrieves
the cached block and another that sets the header and MTE environment.
These were split so that the retrieve function could be more easily
changed in the future and so that the retrieve function had the sole
purpose of retrieving a CachedBlock.

Reviewed By: cferris

Differential Revision: https://reviews.llvm.org/D155660
2023-07-25 19:26:32 +00:00
Marco Nelissen
bf89531c41 [scudo] Enabled MAP_ALLOWNOMEM for all platforms
Back-ported from https://r.android.com/2591905.

Reviewed By: Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D152888
2023-07-25 15:25:26 +00:00
fernandosalas
85c622b597 [scudo] Improve Secondary Cache Dump
Exclude cached blocks with invalid start address. Mainly concerned with
cached blocks that are still available/unused.

Reviewed By: Chia-hungDuan, cferris

Differential Revision: https://reviews.llvm.org/D154148
2023-06-30 20:55:41 +00:00
Christopher Ferris
bd694683eb [scudo] Use fast get time in secondary.
When I moved the primary to use the faster get time syscall, I missed
the secondary use. Now fix the secondary to use this function too.

Reviewed By: Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D154012
2023-06-28 17:29:47 -07:00
fernandosalas
4cf35a85c7 [scudo] Secondary Cache Dump
Dumped some basic info about what is being cached and about the cache
itself. Output of test below:

...
Stats: MapAllocatorCache: EntriesCount: 33, MaxEntriesCount: 64, MaxEntrySize: 1048576
StartBlockAddress: 0x6d342c1000, EndBlockAddress: 0x6d342d2000, BlockSize: 69632
StartBlockAddress: 0x6fc45ff000, EndBlockAddress: 0x6fc462f000, BlockSize: 196608
...

Reviewed By: Chia-hungDuan

Differential Revision: https://reviews.llvm.org/D153483
2023-06-26 22:41:19 +00:00
Caslyn Tonelli
0a168131b4 [scudo] Add 'inline' to static secondary.h function
This patches an error flaged by Fuchsia builds e.g.
https://ci.chromium.org/ui/p/turquoise/builders/global.try/core.x64-asan/b8779376650819379137/overview)

```
build failed:

[87176/332302](525) CXX user.libc_x64-asan-ubsan/obj/zircon/system/ulib/c/scudo/gwp-asan-info.gwp_asan_info.cc.o
FAILED: user.libc_x64-asan-ubsan/obj/zircon/system/ulib/c/scudo/gwp-asan-info.gwp_asan_info.cc.o
../../prebuilt/third_party/python3/linux-x64/bin/python3.8 -S ../../build/rbe/cxx_remote_wrapper.py --exec_strategy=remote_local_fallback --  ../../prebuilt/third_party/clang/linux-x64/bin/clang++ -MD -MF user.libc_x64-asan-ubsan/obj/zircon/system/ulib/c/scudo/gwp-asan-info.gwp_asan_info.cc.o.d -o user.libc_x64-asan-ubsan/obj/zircon/system/ulib/c/scudo/gwp-asan-info.gwp_asan_info.cc.o -D_LIBCPP...
In file included from ../../zircon/system/ulib/c/scudo/gwp_asan_info.cc:7:
In file included from ../../third_party/scudo/src/allocator_config.h:12:
In file included from ../../third_party/scudo/src/combined.h:22:
../../third_party/scudo/src/secondary.h:67:13: error: 'static' function 'unmap' declared in header file should be declared 'static inline' [-Werror,-Wunneeded-internal-declaration]
static void unmap(LargeBlock::Header *H) {
            ^
1 error generated.
```

Differential Revision: https://reviews.llvm.org/D152038
2023-06-02 23:47:27 +00:00
Chia-hung Duan
2f08a08f61 [scudo] Support importing custom configuration
To define custom allocation, you only need to put the configuration in
custom_scudo_config.h and define two required aliases, then you will be
switched to the customized config and the tests will also run with your
configuration.

In this CL, we also have a minor refactor the structure of
configuration. Now the essential fields are put under the associated
hierarchy and which will make the defining new configuration easier.

Reviewed By: cferris

Differential Revision: https://reviews.llvm.org/D150481
2023-06-02 16:28:00 +00:00