Skip to content

Repository files navigation

rtc

Go APIs for hardware RTC access on Linux and native wake scheduling on Windows and macOS. Each backend exposes its actual capabilities; the library never uses system time as a substitute for a hardware clock read.

Derived from cleroux/rtc, under the MIT license. Requires Go 1.25 or newer. The only module dependency is golang.org/x/sys.

go get github.com/lib-x/rtc@v0.1.0

Quick start

clock, err := rtc.OpenDefault()
if err != nil { return err }
defer clock.Close()

wakeAt, err := clock.WakeAfter(8 * time.Hour)
if err != nil { return err }
fmt.Println("Wake requested for", wakeAt)

Import github.com/lib-x/rtc. This code sets an alarm; it does not shut down or suspend the machine. On Windows, the timer is cancelled when the handle closes or the process exits. Keep both alive until the intended wake time. Linux and macOS events persist after Close. Consult PlatformCapabilities() before choosing how to manage process lifetime or a power state.

Platform capabilities

Capability Linux Windows macOS
Hardware clock read (Time) RTC device ErrUnsupported ErrUnsupported
Wake mechanism RTC wake alarm ioctl Native wake-enabled waitable timer System pmset event
Sleep/hibernate resume request Driver/firmware dependent Policy/hardware dependent Model/policy dependent
Power-on request after shutdown Driver/firmware dependent Unsupported Model/firmware dependent
Alarm readback Hardware This instance's target and native signal state OS schedule
Alarm survives close/process exit Yes No Yes
Scope One hardware alarm shared with other software One unnamed timer per instance Events with the selected owner name
Open argument Device path Empty string Stable application owner name
Default /dev/rtc0 Unnamed timer lib-x.rtc

Supported() reports whether a native backend exists for the current OS. Linux (including Go's Android/Linux build target), Windows and macOS have backends. Other OSes compile with stubs returning ErrUnsupported.

PlatformCapabilities() describes the backend contract, not successful hardware probing. PowerOnRequest means the OS/driver can accept a power-on request; it never guarantees that the current machine can boot from full shutdown (S5). SystemReadback is false on Windows because its reported target is process-local, not firmware readback. Successful OS scheduling is not proof of actual wake.

API

Method Purpose
OpenDefault() Open the platform default
Open(identifier) Select a Linux device or macOS owner; Windows requires empty
Time() Read hardware time in UTC; Linux only
WakeAfter(duration) Schedule relative wake, rounded up to a second
SetWakeAlarm(time) Schedule at an absolute UTC second; truncate subseconds
WakeAlarm() Read alarm state within the backend's documented scope
CancelWakeAlarm() Cancel within that scope; safe to repeat
Close() Release the instance; safe to repeat

Methods on one instance are safe for concurrent use. ErrClosed identifies use after close. Wrapped system errors support errors.Is. ErrAlarmMismatch identifies readback failures on Linux/macOS. Writes may already have changed state when a later check fails; inspect WakeAlarm before retrying.

Linux

The OS must maintain the RTC in UTC. Time reads hardware time and WakeAfter uses that reading; neither modifies the system clock. SetWakeAlarm and CancelWakeAlarm verify hardware readback. Device permissions, date limits and wake support depend on the driver. Containers need access to /dev/rtc0. Only one alarm exists per device: coordinate ownership with other applications.

Compared with cleroux/rtc v1.0.0, this backend fixes RTC_WKALM_RD being confused with RTC_ALM_READ, retains a valid date during cancellation, normalizes UTC, verifies writes, and serializes operations against idempotent close. Descriptor creation uses CLOEXEC. This focused API does not include upstream ticker/timer APIs.

Windows

Uses CreateWaitableTimerW and absolute SetWaitableTimer with resume enabled. WakeAfter uses the system clock. The native timer can resume a suspended system if wake timers and firmware policy allow it. It cannot boot a fully shut-down system. If Windows reports resume as unsupported, the library returns ErrUnsupported instead of advertising a successful wake timer.

WakeAlarm reports only this instance's target and native signal status. It does not enumerate global timers or read the hardware RTC. Keep the process running and handle open during sleep/hibernation. Close and process exit cancel the timer.

macOS

Uses /usr/bin/pmset schedule wakeorpoweron, with bounded execution and separate arguments, without a shell. Root permissions are required for modifications. Use a stable unique owner, e.g. rtc.Open("com.example.backup"), to recover and cancel your event after restart. Multiple processes using the same owner must coordinate. Only that owner's exact event is cancelled; global cancelall and system repeating schedules are never used. Conflicting or unrecognized owner records produce errors instead of broad cancellation.

WakeAfter uses the system clock. pmset uses local wall time, so the backend converts UTC to the system timezone and verifies the resulting OS schedule. Ambiguous local timestamps and dates beyond 2068 are rejected. A later system timezone change can affect how schedules are displayed or interpreted; read back before relying on them. Actual power-on support depends on model, firmware, power connection and system policy. The library never claims direct hardware RTC reads.

Testing and references

go test -race ./... uses fake devices, fake native timers or fake command runners. Tests never write real wake events, change power settings or shut down a machine. CI runs tests and vet on Linux, Windows and macOS, and checks Linux arm64 builds. Real sleep/hibernate/S5 wake testing is a separate hardware validation step.

About

RTC wake alarms for Go

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages