To provide the programming interface, the clock device generating the ticks is abstracted through the structure struct clock_event_device, defined in include/linux/clockchips.h:
struct clock_event_device { void (*event_handler)(struct clock_event_device *); int (*set_next_event)(unsigned long evt, struct clock_event_device *); int (*set_next_ktime)(ktime_t expires, struct clock_event_device *); ktime_t next_event; u64 max_delta_ns; u64 min_delta_ns; u32 mult; u32 shift; enum clock_event_state state_use_accessors; unsigned int features; unsigned long retries; int (*set_state_periodic)(struct clock_event_device *); int (*set_state_oneshot)(struct clock_event_device *); int (*set_state_oneshot_stopped)(struct clock_event_device *); int (*set_state_shutdown)(struct clock_event_device *); int (*tick_resume)(struct clock_event_device *); void (*broadcast)(const struct cpumask *mask); void (*suspend)(struct clock_event_device *); void (*resume)(struct clock_event_device *); unsigned long min_delta_ticks; unsigned long max_delta_ticks; const char *name; int rating; int irq; int bound_on; const struct cpumask *cpumask; struct list_head list; struct module *owner; } ____cacheline_aligned;
Here, event_handler is the appropriate routine, assigned by the framework to be called by the low-level handler to run the tick. Depending on the configuration, this clock_event_device could be periodic, one-shot, or ktime based. Out of these three, the appropriate operating mode for the tick device is set through the unsigned int features field, using any of these macros:
#define CLOCK_EVT_FEAT_PERIODIC 0x000001
#define CLOCK_EVT_FEAT_ONESHOT 0x000002
#define CLOCK_EVT_FEAT_KTIME 0x000004
Periodic mode configures the hardware generate the tick once every 1/HZ seconds, while one-shot mode makes the hardware generate the tick after the passage of a specific number of cycles from the current time.
Depending on the use cases and the operating mode, event_handler could be any of these three routines:
- tick_handle_periodic(), which is the default handler for periodic ticks and is defined in kernel/time/tick-common.c.
- tick_nohz_handler() is the low-resolution interrupt handler, used in low res mode. It's defined in kernel/time/tick-sched.c.
- hrtimer_interrupt() is used in high res mode and is defined in kernel/time/hrtimer.c. Interrupts are disabled when it's called.
A clock event device is configured and registered through the routine clockevents_config_and_register(), defined in kernel/time/clockevents.c.