EVENTTIMERS(9)
Okay so bestie, you're looking at the EVENTTIMERS(9) manual page from the Kernel Developer's Manual, and let me tell you, this is the main character energy behind all your kernel time events π
β¨
πΈ NAME πΈ
eventtimers β kernel event timers subsystem ππ
π¦ SYNOPSIS π¦
#include <sys/timeet.h>
struct eventtimer;
typedef int et_start_t(struct eventtimer *et,
sbintime_t first, sbintime_t period);
typedef int et_stop_t(struct eventtimer *et);
typedef void et_event_cb_t(struct eventtimer *et, void *arg);
typedef int et_deregister_cb_t(struct eventtimer *et, void *arg);
struct eventtimer {
SLIST_ENTRY(eventtimer) et_all;
char *et_name;
int et_flags;
#define ET_FLAGS_PERIODIC 1
#define ET_FLAGS_ONESHOT 2
#define ET_FLAGS_PERCPU 4
#define ET_FLAGS_C3STOP 8
#define ET_FLAGS_POW2DIV 16
int et_quality;
int et_active;
uint64_t et_frequency;
sbintime_t et_min_period;
sbintime_t et_max_period;
et_start_t *et_start;
et_stop_t *et_stop;
et_event_cb_t *et_event_cb;
et_deregister_cb_t *et_deregister_cb;
void *et_arg;
void *et_priv;
struct sysctl_oid *et_sysctl;
};
int
et_register(struct eventtimer *et);
int
et_deregister(struct eventtimer *et);
void
et_change_frequency(struct eventtimer *et, uint64_t newfreq);
ET_LOCK();
ET_UNLOCK();
struct eventtimer *
et_find(const char *name, int check, int want);
int
et_init(struct eventtimer *et, et_event_cb_t *event,
et_deregister_cb_t *deregister, void *arg);
int
et_start(struct eventtimer *et, sbintime_t first, sbintime_t period);
int
et_stop(struct eventtimer *et);
int
et_ban(struct eventtimer *et);
int
et_free(struct eventtimer *et);
π DESCRIPTION π
Event timers are the literal MVPs that generate interrupts at a specific time or periodically, so all your time-based events can happen. The whole subsystem is split into three main parts:
- Drivers β They manage the hardware to generate the time events you request. Total hardware girlies π§
- Consumers β
sys/kern/kern_clocksource.cuses event timers to supply the kernel withhardclock(),statclock(), andprofclock()time events. They're the ones actually using the tea β - Glue code β
sys/sys/timeet.handsys/kern/kern_et.cprovide the APIs that connect event timer drivers and consumers. The matchmakers of the kernel π
π DRIVER API π
The Driver API is built around the eventtimer structure. To register their functionality, drivers allocate that structure and call et_register(). Here's what the driver should fill in:
et_nameβ Unique name of the event timer for management purposes. Give it a cute one, bestie πet_flagsβ Set of flags describing what the timer can do:ET_FLAGS_PERIODIC1β Periodic mode is supported. It repeats!ET_FLAGS_ONESHOT2β One-shot mode is supported. One and done.ET_FLAGS_PERCPU4β Timer is per-CPU. Every core gets its own.ET_FLAGS_C3STOP8β Timer may stop when the CPU is in a sleep state. It's napping π΄ET_FLAGS_POW2DIV16β Timer supports only 2^n divisors. Math is mathing.
et_qualityβ An abstract value to certify whether this timecounter is better than the others. Higher value means better. It's the vibe check for timers πet_frequencyβ Timer oscillator's base frequency, if applicable and known. Consumers use it to predict the possible frequencies you can get by dividing it. Should be zero if not applicable or unknown. Zero means "we don't know, don't come for us" π€·ββοΈet_min_period,et_max_periodβ Minimal and maximal reliably programmable time periods. The range where the timer actually slays.et_startβ Driver's timer start function pointer. The "go" button πet_stopβ Driver's timer stop function pointer. The "stop" button πet_privβ Driver's private data storage. Their little secret stash π
After the event timer functionality is registered, it's controlled via the et_start and et_stop methods. The et_start method is called to start the specified event timer. The last two arguments specify when events should be generated: the first argument is the time period before the first event is generated. In periodic mode, a NULL value for first means the first period is equal to the period argument value. The period argument specifies the time period between following events for periodic mode. A NULL value there specifies one-shot mode. At least one of these two arguments should be not NULL β no cap π
When the event time arrives, the driver should call the et_event_cb callback function, passing et_arg as the second argument. The et_stop method is called to stop the specified event timer. For per-CPU event timers, the et_start and et_stop methods control timers associated with the current CPU.
Drivers can deregister their functionality by calling et_deregister().
If the frequency of the clock hardware can change while it's running (for example, during power-saving modes), the driver must callet_change_frequency()on each change. If the given event timer is the active timer,et_change_frequency()stops the timer on all CPUs, updateset->frequency, then restarts the timer on all CPUs so that all current events are rescheduled using the new frequency. If the given timer is not currently active,et_change_frequency()simply updateset->frequency. It's giving responsible adult energy β¨
π§ CONSUMER API π§
et_find() lets a consumer find an available event timer, optionally matching a specific name and/or capability flags. Consumers may read the returned eventtimer structure, but they should not modify it. Read-only, hands off π
ββοΈ
When the wanted event timer is found, et_init() should be called for it, submitting the event and optionally deregister callback functions, and the opaque argument arg. That argument will be passed as an argument to the callbacks. The event callback function will be called on scheduled time events. It's called from the hardware interrupt context, so no sleep is permitted there β you can't be catching Z's in an interrupt, bestie π
The deregister callback function may be called to report to the consumer that the event timer functionality is no longer available. On this call, the consumer should stop using the event timer before returning.
After the timer is found and initialized, it can be controlled via et_start() and et_stop(). The arguments are the same as described in the driver API. Per-CPU event timers can be controlled only from specific CPUs.
et_ban() allows a consumer to mark an event timer as broken by clearing both one-shot and periodic capability flags, if it was somehow detected. It's the "you're cancelled" button π
et_free() is the opposite of et_init(). It releases the event timer for other consumers to use. Sharing is caring π«Ά
ET_LOCK() and ET_UNLOCK() macros should be used to manage a mutex(9) lock around et_find(), et_init(), and et_free() calls to serialize access to the list of registered event timers and the pointers returned by et_find(). et_start() and et_stop() calls should be serialized in the consumer's internal way to avoid concurrent timer hardware access. Locking is self-care, periodt π
π SEE ALSO π
eventtimers(4) β go check it out, bestie! It's the user-facing bestie of this page π
π AUTHORS π
Alexander Motin <mav@FreeBSD.org> β absolute legend for writing this, we stan π
This page is from Debian, dated April 2, 2014, and it's the EVENTTIMERS(9) manual page. Slay. π
π¦ where this page comes from
- freebsd 14.5: base 14.5
- freebsd 15.1: base 15.1
- Copyright (c) 2011-2013 Alexander Motin <mav@FreeBSD.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms