PatchworkOS  19e446b
A non-POSIX operating system.
Loading...
Searching...
No Matches
timer.h
Go to the documentation of this file.
1#pragma once
2
4#include <kernel/cpu/irq.h>
5#include <kernel/sync/lock.h>
6
7#include <sys/proc.h>
8#include <time.h>
9
10typedef struct cpu cpu_t;
11
12/**
13 * @brief Per-CPU timers.
14 * @defgroup kernel_timer Timer subsystem
15 * @ingroup kernel_sched
16 *
17 * The timer subsystem is responsible for managing per-CPU timers which are responsible for generating timer interrupts.
18These interrupts are whats called "one-shot" interrupts, meaning that the interrupt will only occur once and then a new
19interrupt must be programmed.
20 *
21 * ## Timer Interrupts
22 *
23 * The way we handle timer interrupts is that each subsystem that relies on the timer calls the `timer_set()` function
24with their desired deadline and then, when the timer interrupt occurs, the timer interrupt is acknowledged and the usual
25interrupt handling process continues. For example, the scheduler and wait system will check if they need to do anything.
26 *
27 * Both the scheduler and the wait system can now call `timer_set()` again if they need to schedule another timer
28interrupt or if the time they requested has not yet occurred.
29 *
30 * This does technically result in some uneeded checks but its a very simply way of effectively eliminating timer
31related race conditions.
32 *
33 * ## Timer Sources
34 *
35 * The actual timer interrupts are provided by "timer sources" (`timer_source_t`), which are registered by modules. Each
36source registers itself with a estimate of its precision, the timer subsystem then chooses the source with the highest
37precision as the active timer source.
38 *
39 * @{
40 */
41
42/**
43 * @brief Maximum amount of timer sources.
44 */
45#define TIMER_MAX_SOURCES 4
46
47/**
48 * @brief Timer source structure.
49 * @struct timer_source_t
50 */
51typedef struct
52{
53 const char* name;
55 /**
56 * @brief Should set the one-shot timer to fire after the specified timeout.
57 *
58 * Should panic on failure, as failing to set a timer will almost certainly result in the system hanging.
59 *
60 * @param virt The virtual IRQ to use for the timer interrupt, usually `VECTOR_TIMER`.
61 * @param uptime The current uptime in nanoseconds.
62 * @param timeout The desired timeout in nanoseconds, if `CLOCKS_NEVER`, the timer should be disabled.
63 */
64 void (*set)(irq_virt_t virt, clock_t uptime, clock_t timeout);
65 void (*ack)(void);
66 void (*eoi)(void);
68
69/**
70 * @brief Acknowledge a timer interrupt and send EOI.
71 *
72 * @param frame The interrupt frame of the timer interrupt.
73 */
75
76/**
77 * @brief Register a timer source.
78 *
79 * @param source The timer source to register.
80 * @return On success, `0`. On failure, `ERR` and `errno` is set to:
81 * - `EINVAL`: Invalid parameters.
82 * - `ENOSPC`: No more timer sources can be registered.
83 * - Other errors as returned by `irq_handler_register()`.
84 */
86
87/**
88 * @brief Unregister a timer source.
89 *
90 * @param source The timer source to unregister, or `NULL` for no-op.
91 */
93
94/**
95 * @brief Get the amount of registered timer sources.
96 *
97 * @return The amount of registered timer sources.
98 */
100
101/**
102 * @brief Schedule a one-shot timer interrupt on the current CPU.
103 *
104 * Sets the per-cpu timer to generate a interrupt after the specified timeout.
105 *
106 * Multiple calls with different timeouts will result in the timer being set for the shortest requested timeout, this
107 * will be reset after a timer interrupt.
108 *
109 * The reason we need to specify the current uptime, is not just as a slight optimization, but also to ensure the caller
110 * knows exactly what time they are scheduling the timer for, as the uptime could change between the caller reading the
111 * time and this function setting the timer, resulting in very subtle bugs or race conditions.
112 *
113 * @note Will never set the timeout to be less than `CONFIG_MIN_TIMER_TIMEOUT` to avoid spamming the CPU with timer
114 * interrupts.
115 *
116 * @param now The time since boot, we need to specify this as an argument to avoid inconsistency in the
117 * timeout/deadline calculations.
118 * @param deadline The desired deadline.
119 */
120void timer_set(clock_t now, clock_t deadline);
121
122/** @} */
uint8_t irq_virt_t
Virtual IRQ numbers.
Definition irq.h:57
static clock_source_t source
Structure to describe the HPET to the sys time subsystem.
Definition hpet.c:193
uint64_t timer_source_amount(void)
Get the amount of registered timer sources.
Definition timer.c:131
void timer_source_unregister(const timer_source_t *source)
Unregister a timer source.
Definition timer.c:93
void timer_ack_eoi(interrupt_frame_t *frame)
Acknowledge a timer interrupt and send EOI.
Definition timer.c:33
uint64_t timer_source_register(const timer_source_t *source)
Register a timer source.
Definition timer.c:54
void timer_set(clock_t now, clock_t deadline)
Schedule a one-shot timer interrupt on the current CPU.
Definition timer.c:139
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
CPU structure.
Definition cpu.h:84
Trap Frame Structure.
Definition interrupt.h:195
Timer source structure.
Definition timer.h:52
const char * name
Definition timer.h:53
clock_t precision
Definition timer.h:54