darwin: fix memory meter showing ~64 TB on ARM64 due to unsigned underflow#1952
Conversation
|
Possible fix for #1953 |
|
htop has a macro called saturatingSub() (in Macros.h). Maybe it's better to use that instead of cast to |
|
By the way, how did you capture the numbers as reported here?
I hope these numbers are not made up. |
Let me double check |
|
@Explorer09 Good call, updated. Using saturatingSub() with promotion to unsigned long long before the intermediate addition to stay safe across the full range. About numbers these are live values captured from vm_stat on the affected system (M4 Max, 48 GB, macOS Sequoia). The command:
The key condition is external_page_count > active_count - purgeable_count, which is a normal state on macOS when the file cache is large (e.g. right after boot or heavy file I/O). |
I have an M2 MacBook, but unfortunately my use cases with a Mac didn't involve in a large number of file-backed pages. In other words I cannot reproduce the issue during my normal use. |
|
Please squash/fixup the commits into one as per our style guide … |
ecb76f5 to
4a28727
Compare
On macOS with Apple Silicon (16K pages), external_page_count (file-backed pages) can exceed active_count, causing the unsigned subtraction in Platform_setMemoryValues to wrap around to ~4 billion pages. This results in the memory meter displaying ~64 TB of used memory instead of the actual value. Use saturatingSub() to clamp the result to zero when the subtraction would underflow. Intermediate additions are promoted to unsigned long long to avoid narrowing before the saturating check. Affects both showCachedMemory=true and showCachedMemory=false paths.
4a28727 to
b3826b5
Compare
Problem
On macOS with Apple Silicon, the memory meter can display wildly incorrect
values — typically ~64 TB used out of 48 GB total. This makes the memory
bar completely unusable.
The root cause is an unsigned integer underflow in
Platform_setMemoryValues()(
darwin/Platform.c). The active page count is computed as:All three variables are
natural_t(unsigned 32-bit). On systems wherefile-backed pages (
external_page_count) exceedactive_count - purgeable_count,the subtraction wraps around to ~4,294,867,000 pages. Multiplied by
page_K(16 for ARM64's 16 KB pages), this produces ~64 TB.Example from a live system (M4 Max, 48 GB RAM):
This is a normal state on macOS — the file cache often exceeds
active pages, especially after boot or heavy file I/O.
Fix
Cast each page count to
doublebefore subtraction so the arithmeticis signed, and clamp the result to zero using the existing
MAXIMUM()macro. This avoids the wraparound while preserving the original
calculation semantics.
Both the
showCachedMemory=trueandshowCachedMemory=falsecode pathsare fixed.
Before / After
Test
Built and ran on macOS Sequoia 15.x, Apple M4 Max (48 GB).
Memory meter now shows correct values consistent with
topandvm_stat.