wake_clock_darwin.go 1.1 KB

1234567891011121314151617181920212223242526272829
  1. //go:build darwin
  2. package nebula
  3. import (
  4. "time"
  5. "golang.org/x/sys/unix"
  6. )
  7. // suspendClockDelta returns CLOCK_MONOTONIC - CLOCK_UPTIME_RAW. On macOS CLOCK_MONOTONIC keeps counting across
  8. // system sleep while CLOCK_UPTIME_RAW (mach_absolute_time) pauses, so the difference grows by time spent asleep.
  9. //
  10. // The pausing clock is read first so scheduling jitter between the two reads biases the delta positive; the
  11. // wakeDetector clamps out the noise.
  12. //
  13. // Caveat: on Apple Silicon the hardware timebase keeps ticking through sleep, which can make both clocks advance
  14. // and the spread stay flat, leaving this detector blind. That fails safe (no clears, behavior as before); IOKit
  15. // power notifications are the follow-up for full coverage on those machines.
  16. func suspendClockDelta() (time.Duration, bool) {
  17. var uptime, mono unix.Timespec
  18. if err := unix.ClockGettime(unix.CLOCK_UPTIME_RAW, &uptime); err != nil {
  19. return 0, false
  20. }
  21. if err := unix.ClockGettime(unix.CLOCK_MONOTONIC, &mono); err != nil {
  22. return 0, false
  23. }
  24. return time.Duration(mono.Nano() - uptime.Nano()), true
  25. }