Skip to content

Power Management

pkgdemon edited this page Oct 24, 2026 · 3 revisions

Power management on NextBSD is early. One command ships today, caffeinate(8), and it accepts everything Darwin's does. The assertions it creates are not yet enforced, so it will not actually keep a machine awake. The interface is real, the plumbing behind it is not, and that is worth knowing before you rely on it.

The rest of this page says what works now, what does not, and what is coming.

caffeinate(8)

Darwin's way of saying "do not sleep while this matters". Run it with a command and the assertion lasts as long as that command:

caffeinate -i make -j8            # no idle sleep while the build runs
caffeinate -d mpv film.mkv        # no display sleep while watching
caffeinate -is ./long-job.sh      # no idle and no system sleep

Run it without a command and it holds the assertion until you interrupt it:

caffeinate -i                     # until Ctrl-C
caffeinate -i -t 3600             # for an hour, then exit
caffeinate -i -w 4242             # until process 4242 exits
Flag Meaning
-i prevent idle sleep. The default when no assertion flag is given.
-d prevent the display sleeping
-m prevent the disk idling
-s prevent system sleep
-u declare the user active
-t seconds hold the assertion for this long, then exit
-w pid hold it until that process exits
-h usage

Those are Darwin's flags, unchanged, so a script written for a Mac runs here without editing.

What works and what does not

Works. The command, its flags, the man page, and the process handling. caffeinate cmd runs cmd, waits for it and exits with its status. caffeinate -w pid waits for that process. -t expires on time. The IOPMAssertion functions exist in libIOKit, so a program that links against them compiles and runs.

Does not work yet. Nothing is actually kept awake. IOPMAssertionCreateWithDescription hands back a unique assertion identifier and returns success, and IOPMAssertionRelease, IOPMAssertionRetain and IOPMAssertionSetProperty all return success, but no daemon is listening and no policy consults them. There is also no pmset, no battery reporting, and no suspend or resume.

So treat caffeinate today as the interface landing ahead of the machinery. That is a deliberate order: it lets the API and the command settle, and lets other software link against IOPMAssertion, while the daemon and the kernel side are built underneath.

Thanks

caffeinate and the IOPMAssertion stubs were ported by @isaim0011 in nextbsd-userland#245, the first contribution to NextBSD's power management. Thank you.

What is coming

Tracked as EPIC: E17 Power management, twenty tickets across the userland and the kernel, none finished yet. The shape of the work, in the order it has to happen:

The kernel has to grow the hooks first. FreeBSD has no IOPMrootDomain, so there is nothing for a power daemon to talk to. That means an iopmroot bridge driver exposing a device node, IORegistry interest notifications so a daemon can be told when something changes, IOPMPowerSource nodes for ACPI batteries and AC, and an ACPI sleep path that waits for a registered listener instead of suspending immediately. Two of those are spikes rather than plans: an in-kernel IOPMrootDomain, and whether a wake alarm is reachable at all, since FreeBSD has no rtcwake.

Then pmconfigd, Apple's power management daemon, vendored and booted. That is what turns the assertion API from a stub into a policy: an assertion engine and idle-sleep policy, S3 sleep and wake orchestration, power sources read from the kernel nodes, and CPU power policy that changes with AC or battery.

Then the rest of the client side. IOPowerSources, so software can ask about the battery; IORegisterForSystemPower, so software can be told the machine is about to sleep and object; and power state published into the system configuration store.

Once the assertion engine lands, caffeinate starts working with no change to the command itself. That is the point of the ordering.

See also

Clone this wiki locally