gpui: Drop foreground measurements that span an unnotified system suspend (#64891)

## Summary

Hang telemetry still reports foreground task polls lasting minutes to
hours, mostly on Windows. #64269 drops measurements interrupted by
sleep, but it relies on power notifications. Those are delivered on the
foreground thread, so when the system suspends mid-poll, the poll
finishes and is recorded *before* the notification is handled. On
Windows the notification can also be dropped. The Windows clock behind
`Instant` (QPC) keeps counting through sleep, so one missed ordering
becomes an hours-long "stall".

This change makes each measurement check a suspend clock, with no
dependence on notification ordering.

## How it works

- `system_suspended_time()` returns total time suspended since boot, as
the difference between a clock that counts suspended time and one that
doesn't. Every read is served from kernel-mapped memory, with no syscall
on the normal path:
  - **Linux/Android:** `CLOCK_BOOTTIME − CLOCK_MONOTONIC`
- **macOS:** `mach_continuous_time() − mach_absolute_time()`
(`<mach/mach_time.h>` documents the former as "like mach_absolute_time,
but advances during sleep"), converted with a cached
`mach_timebase_info`. Measured at ~4 ns per read on Apple silicon.
  - **Windows:** `QueryInterruptTime − QueryUnbiasedInterruptTime`
- **Other platforms:** `None`, which keeps the notification-only
behavior.
- `detect_suspend` runs at the start of each foreground turn (before the
turn's work takes its start time, so a suspend while idle never drops
later work) and wherever a measurement ends (task poll end,
`power_interrupted_since`, `frame_sample_is_valid`). If suspended time
grew by at least 50 ms (`MIN_DETECTED_SUSPEND`, above Windows'
up-to-15.6 ms tick jitter), it runs the same `interrupt_measurements`
routine a power notification runs:
- seals the open interval with a `PowerTransition` boundary, so earlier
small work can't add up to a budget incident across the suspend;
- sets `power_changed_at`, so any measurement that started before it is
dropped;
  - clears pending `dirty_at` for each window.
- Handling a power notification refreshes the stored reading, so a
notified suspend isn't counted twice.
- Measurements that span a suspend are dropped rather than corrected: on
Linux, process freeze and thaw around the suspend add seconds that no
clock excludes.

`MEASUREMENT_VERSION` stays at 2; it will be bumped once alongside the
planned schema changes.

Dependencies: `gpui` gains a direct `libc` dependency on Linux/Android
only (it was already in the build graph through 15+ dependencies at the
same version), and the `Win32_System_WindowsProgramming` feature of the
existing `windows` dependency. The macOS mach functions are declared in
a small `extern "C"` block because libc deprecates its mach bindings.

## Not covered

- Freezes where the system stays awake (debugger, SIGSTOP, cgroup
freezer) and genuinely blocked polls. A follow-up watchdog will classify
these.
- Hangs that never complete.

## Testing

- New tests: a poll spanning an un-notified suspend is dropped, a
boundary is emitted, and the pending frame is cleared; notified suspends
and sub-threshold jitter do not interrupt. Journals installed by tests
use a fake suspend clock, so a real suspend during a test run can't
affect results.
- `cargo test -p gpui --features profiler --lib -- profiler::`: 55
passed. `./script/clippy -p gpui --features profiler` and `cargo fmt`
are clean. `cargo check` passes for `x86_64-unknown-linux-gnu` and
`x86_64-pc-windows-msvc`.
- Manual test on macOS (Apple silicon, debug build) with a temporary
action that blocks the foreground executor for 60 s:
- Control, no sleep: a `Threshold` incident of ~10,000 ms is reported
for a 10 s block.
- Lid closed during the 60 s block: `pmset -g log` shows Clamshell Sleep
at 10:32:27 and wake at 10:34:01. The block ended at 10:34:17 (144 s
wall clock), the suspend clock detected 84.2 s suspended, and **no**
hang incident was reported for the block.
- Note: macOS delays sleep for up to 30 s while an
`NSWorkspaceWillSleepNotification` observer is blocked (`pmset` logged
`zed timed out(30000 ms)`), so on macOS only polls longer than ~30 s can
span a suspend. Windows and Linux are not yet manually tested.

Release Notes:

- [GPUI] Improved hang telemetry accuracy by dropping foreground
measurements that span a system suspend, even when the platform's sleep
notification arrives late or not at all
7232ba04efAnthony Eid committed on 9/29/2026, 4:23:47 PM· committed by GitHubparent1dc8844
3 files changedLine totals unavailable