From 42547104d6f6064d2637517c274172388cd68944 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Mon, 23 Mar 2026 02:58:24 +0100 Subject: [PATCH 01/22] Add rough skeleton for clock controller --- include/stdbigos/clock.h | 22 +++++++++++++++++ src/example_sbi/entry.c | 44 +++++++++++++++++++++++++++++++++- src/lib/stdbigos/clock.c | 51 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 include/stdbigos/clock.h create mode 100644 src/lib/stdbigos/clock.c diff --git a/include/stdbigos/clock.h b/include/stdbigos/clock.h new file mode 100644 index 00000000..15d2ab07 --- /dev/null +++ b/include/stdbigos/clock.h @@ -0,0 +1,22 @@ +#ifndef STDBIGOS_CLOCK +#define STDBIGOS_CLOCK + +#include "sbi.h" +#include "types.h" + +/// @ingroup stdbigos +/// @{ +/// @ingroup clock +/// @{ + +u64 clock_now(void); +u64 clock_ticks(void); + +struct sbiret clock_init(u64 tick_quantum); +struct sbiret clock_rearm(void); +struct sbiret clock_on_timer_interrupt(void); + +/// @} +/// @} + +#endif // !STDBIGOS_CLOCK diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index 53fe6f0e..0ec1dce5 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -1,10 +1,52 @@ +#include +#include #include +#include #include +#include static void sbi_puts(const char* str) { while (*str) sbi_debug_console_write_byte(*str++); } +[[gnu::interrupt("supervisor")]] +static void int_handler() { + reg_t cause = CSR_READ(scause); + if (!is_interrupt(cause)) { + return; + } + + reg_t int_no = get_interrupt_code(cause); + if (int_no != IntSTimer) { + return; + } + + (void)clock_on_timer_interrupt(); +} + void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { - sbi_puts("Hello world\n"); + CSR_WRITE(stvec, int_handler); + + struct sbiret ret = clock_init(50000llu); + if (ret.error != SBI_SUCCESS) { + sbi_puts("clock init failed\n"); + return; + } + + CSR_SET(sie, 1lu << IntSTimer); + CSR_SET(sstatus, 1lu << 1); + + sbi_puts("clock started\n"); + + u64 last_tick = 0; + while (true) { + wfi(); + + u64 ticks = clock_ticks(); + if (ticks != last_tick && (ticks % 100) == 0) { + sbi_puts("tick x100\n"); + } + + last_tick = ticks; + } } diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c new file mode 100644 index 00000000..9d8ffab3 --- /dev/null +++ b/src/lib/stdbigos/clock.c @@ -0,0 +1,51 @@ +#include +#include + +static u64 g_tick_quantum; +static u64 g_next_deadline; +static u64 g_ticks; + +static struct sbiret clock_program_timer(u64 deadline) { + struct sbiret ret = sbi_set_timer(deadline); + if (ret.error == SBI_ERR_NOT_SUPPORTED) { + return sbi_legacy_set_timer(deadline); + } + + return ret; +} + +static struct sbiret make_error(sbi_error_t error) { + return (struct sbiret){.error = error, .value = 0}; +} + +u64 clock_now(void) { + return CSR_READ(time); +} + +u64 clock_ticks(void) { + return g_ticks; +} + +struct sbiret clock_rearm(void) { + if (g_tick_quantum == 0) { + return make_error(SBI_ERR_INVALID_STATE); + } + + g_next_deadline = clock_now() + g_tick_quantum; + return clock_program_timer(g_next_deadline); +} + +struct sbiret clock_init(u64 tick_quantum) { + if (tick_quantum == 0) { + return make_error(SBI_ERR_INVALID_PARAM); + } + + g_ticks = 0; + g_tick_quantum = tick_quantum; + return clock_rearm(); +} + +struct sbiret clock_on_timer_interrupt(void) { + ++g_ticks; + return clock_rearm(); +} From 67f6d62ada71f3ef9f00cf37d4bc40a7b90e39b5 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Mon, 23 Mar 2026 03:19:41 +0100 Subject: [PATCH 02/22] Test commit signing From 827960d3a8e03f10e965adc93457e60c35855d14 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sun, 19 Apr 2026 22:57:27 +0200 Subject: [PATCH 03/22] Add HAL timer abstraction --- include/hal/timer.h | 46 +++++++++++++++++++++++++++++++ src/example_sbi/CMakeLists.txt | 2 +- src/example_sbi/entry.c | 33 +++++++++++----------- src/lib/hal/arch/riscv/csr_vals.h | 2 ++ src/lib/hal/arch/riscv/timer.c | 44 +++++++++++++++++++++++++++++ src/lib/stdbigos/clock.c | 33 ++++++++++++++-------- 6 files changed, 131 insertions(+), 29 deletions(-) create mode 100644 include/hal/timer.h create mode 100644 src/lib/hal/arch/riscv/timer.c diff --git a/include/hal/timer.h b/include/hal/timer.h new file mode 100644 index 00000000..b345cc3b --- /dev/null +++ b/include/hal/timer.h @@ -0,0 +1,46 @@ +#ifndef HAL_TIMER_H +#define HAL_TIMER_H + +#include +#include + +/** + * @addtogroup hal + * @{ + */ + +/** + * @brief Read current monotonic hardware timer value. + */ +u64 hal_timer_now(void); + +/** + * @brief Program the next timer interrupt deadline. + * + * @param deadline Absolute timer value when the interrupt should fire. + * @retval ERR_NONE Success + * @retval ERR_BAD_ARG Invalid deadline argument + * @retval ERR_NOT_IMPLEMENTED Timer SBI extension unsupported + * @retval ERR_NOT_VALID Other platform/firmware failure + */ +error_t hal_timer_set_deadline(u64 deadline); + +/** + * @brief Program next timer interrupt relative to current time. + * + * @param delta Timer ticks from now + * @retval ERR_NONE Success + * @retval ERR_BAD_ARG Invalid delta argument + * @retval ERR_NOT_IMPLEMENTED Timer SBI extension unsupported + * @retval ERR_NOT_VALID Other platform/firmware failure + */ +error_t hal_timer_arm_relative(u64 delta); + +/** + * @brief Enable supervisor timer interrupts and global supervisor IRQs. + */ +error_t hal_timer_enable_interrupts(void); + +/// @} + +#endif // !HAL_TIMER_H diff --git a/src/example_sbi/CMakeLists.txt b/src/example_sbi/CMakeLists.txt index 5612d64e..b26491e6 100644 --- a/src/example_sbi/CMakeLists.txt +++ b/src/example_sbi/CMakeLists.txt @@ -1,5 +1,5 @@ SETUP_EXECUTABLE(example_sbi) -target_link_libraries(example_sbi PRIVATE startup stdbigos) +target_link_libraries(example_sbi PRIVATE startup stdbigos hal) ADD_QEMU_TARGET(example_sbi) diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index 0ec1dce5..6d8ad04f 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -1,7 +1,7 @@ #include -#include +#include +#include #include -#include #include #include @@ -9,38 +9,37 @@ static void sbi_puts(const char* str) { while (*str) sbi_debug_console_write_byte(*str++); } -[[gnu::interrupt("supervisor")]] -static void int_handler() { - reg_t cause = CSR_READ(scause); - if (!is_interrupt(cause)) { +static void timer_handler(void) { + (void)clock_on_timer_interrupt(); +} + +void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { + if (hal_trap_init() != ERR_NONE) { + sbi_puts("trap init failed\n"); return; } - reg_t int_no = get_interrupt_code(cause); - if (int_no != IntSTimer) { + if (hal_trap_register_timer_handler(timer_handler) != ERR_NONE) { + sbi_puts("timer handler register failed\n"); return; } - (void)clock_on_timer_interrupt(); -} - -void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { - CSR_WRITE(stvec, int_handler); - struct sbiret ret = clock_init(50000llu); if (ret.error != SBI_SUCCESS) { sbi_puts("clock init failed\n"); return; } - CSR_SET(sie, 1lu << IntSTimer); - CSR_SET(sstatus, 1lu << 1); + if (hal_timer_enable_interrupts() != ERR_NONE) { + sbi_puts("timer irq enable failed\n"); + return; + } sbi_puts("clock started\n"); u64 last_tick = 0; while (true) { - wfi(); + hal_wait_for_interrupt(); u64 ticks = clock_ticks(); if (ticks != last_tick && (ticks % 100) == 0) { diff --git a/src/lib/hal/arch/riscv/csr_vals.h b/src/lib/hal/arch/riscv/csr_vals.h index 0f336d8a..f422405a 100644 --- a/src/lib/hal/arch/riscv/csr_vals.h +++ b/src/lib/hal/arch/riscv/csr_vals.h @@ -19,4 +19,6 @@ #define CSR_SSTATUS_UXL_MASK 0b11 #define CSR_SSTATUS_SD (1ul << 63) +#define CSR_SIE_STIE (1ul << 5) + #endif // !HAL_RISCV_CSR_VALS diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c new file mode 100644 index 00000000..a0324f21 --- /dev/null +++ b/src/lib/hal/arch/riscv/timer.c @@ -0,0 +1,44 @@ +#include +#include + +#include "csr.h" + +static error_t map_sbi_error(sbi_error_t err) { + switch (err) { + case SBI_SUCCESS: return ERR_NONE; + case SBI_ERR_INVALID_PARAM: return ERR_BAD_ARG; + case SBI_ERR_NOT_SUPPORTED: return ERR_NOT_IMPLEMENTED; + default: return ERR_NOT_VALID; + } +} + +u64 hal_timer_now(void) { + return CSR_READ(time); +} + +error_t hal_timer_set_deadline(u64 deadline) { + if (deadline == 0) { + return ERR_BAD_ARG; + } + + struct sbiret ret = sbi_set_timer(deadline); + if (ret.error == SBI_ERR_NOT_SUPPORTED) { + ret = sbi_legacy_set_timer(deadline); + } + + return map_sbi_error(ret.error); +} + +error_t hal_timer_arm_relative(u64 delta) { + if (delta == 0) { + return ERR_BAD_ARG; + } + + return hal_timer_set_deadline(hal_timer_now() + delta); +} + +error_t hal_timer_enable_interrupts(void) { + CSR_SET(sie, CSR_SIE_STIE); + CSR_SET(sstatus, CSR_SSTATUS_SIE); + return ERR_NONE; +} diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index 9d8ffab3..1835423e 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -1,25 +1,36 @@ #include -#include +#include static u64 g_tick_quantum; static u64 g_next_deadline; static u64 g_ticks; -static struct sbiret clock_program_timer(u64 deadline) { - struct sbiret ret = sbi_set_timer(deadline); - if (ret.error == SBI_ERR_NOT_SUPPORTED) { - return sbi_legacy_set_timer(deadline); +static sbi_error_t map_hal_error(error_t err) { + switch (err) { + case ERR_NONE: return SBI_SUCCESS; + case ERR_BAD_ARG: return SBI_ERR_INVALID_PARAM; + case ERR_NOT_INITIALIZED: + case ERR_NOT_VALID: return SBI_ERR_INVALID_STATE; + case ERR_NOT_IMPLEMENTED: return SBI_ERR_NOT_SUPPORTED; + default: return SBI_ERR_FAILED; } +} - return ret; +static struct sbiret make_error(error_t error) { + return (struct sbiret){.error = map_hal_error(error), .value = 0}; } -static struct sbiret make_error(sbi_error_t error) { - return (struct sbiret){.error = error, .value = 0}; +static struct sbiret clock_program_timer(u64 deadline) { + error_t err = hal_timer_set_deadline(deadline); + if (err != ERR_NONE) { + return make_error(err); + } + + return (struct sbiret){.error = SBI_SUCCESS, .value = 0}; } u64 clock_now(void) { - return CSR_READ(time); + return hal_timer_now(); } u64 clock_ticks(void) { @@ -28,7 +39,7 @@ u64 clock_ticks(void) { struct sbiret clock_rearm(void) { if (g_tick_quantum == 0) { - return make_error(SBI_ERR_INVALID_STATE); + return make_error(ERR_NOT_INITIALIZED); } g_next_deadline = clock_now() + g_tick_quantum; @@ -37,7 +48,7 @@ struct sbiret clock_rearm(void) { struct sbiret clock_init(u64 tick_quantum) { if (tick_quantum == 0) { - return make_error(SBI_ERR_INVALID_PARAM); + return make_error(ERR_BAD_ARG); } g_ticks = 0; From f4b48868834787145415804cee320d373626cd91 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sun, 19 Apr 2026 23:18:29 +0200 Subject: [PATCH 04/22] Switch clock handling to one-shot timer behavior --- src/example_sbi/entry.c | 12 +++--------- src/lib/stdbigos/clock.c | 8 +++++++- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index 6d8ad04f..a3a88cbd 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -37,15 +37,9 @@ void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { sbi_puts("clock started\n"); - u64 last_tick = 0; - while (true) { + while (clock_ticks() == 0) { hal_wait_for_interrupt(); - - u64 ticks = clock_ticks(); - if (ticks != last_tick && (ticks % 100) == 0) { - sbi_puts("tick x100\n"); - } - - last_tick = ticks; } + + sbi_puts("tick one-shot\n"); } diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index 1835423e..3ed1cc3a 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -58,5 +58,11 @@ struct sbiret clock_init(u64 tick_quantum) { struct sbiret clock_on_timer_interrupt(void) { ++g_ticks; - return clock_rearm(); + + error_t err = hal_timer_set_deadline(~0ull); + if (err != ERR_NONE) { + return make_error(err); + } + + return (struct sbiret){.error = SBI_SUCCESS, .value = 0}; } From 67a442176be895f78a1e0d23987247d04c80933f Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sun, 19 Apr 2026 23:22:38 +0200 Subject: [PATCH 05/22] Refactor stdbigos clock API to return error_t --- include/stdbigos/clock.h | 8 ++++---- src/example_sbi/entry.c | 4 ++-- src/lib/stdbigos/clock.c | 35 ++++++++++------------------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/include/stdbigos/clock.h b/include/stdbigos/clock.h index 15d2ab07..b90868ff 100644 --- a/include/stdbigos/clock.h +++ b/include/stdbigos/clock.h @@ -1,7 +1,7 @@ #ifndef STDBIGOS_CLOCK #define STDBIGOS_CLOCK -#include "sbi.h" +#include "error.h" #include "types.h" /// @ingroup stdbigos @@ -12,9 +12,9 @@ u64 clock_now(void); u64 clock_ticks(void); -struct sbiret clock_init(u64 tick_quantum); -struct sbiret clock_rearm(void); -struct sbiret clock_on_timer_interrupt(void); +error_t clock_init(u64 tick_quantum); +error_t clock_rearm(void); +error_t clock_on_timer_interrupt(void); /// @} /// @} diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index a3a88cbd..e7f650a1 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -24,8 +24,8 @@ void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { return; } - struct sbiret ret = clock_init(50000llu); - if (ret.error != SBI_SUCCESS) { + error_t err = clock_init(50000llu); + if (err != ERR_NONE) { sbi_puts("clock init failed\n"); return; } diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index 3ed1cc3a..a9845dc7 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -5,28 +5,13 @@ static u64 g_tick_quantum; static u64 g_next_deadline; static u64 g_ticks; -static sbi_error_t map_hal_error(error_t err) { - switch (err) { - case ERR_NONE: return SBI_SUCCESS; - case ERR_BAD_ARG: return SBI_ERR_INVALID_PARAM; - case ERR_NOT_INITIALIZED: - case ERR_NOT_VALID: return SBI_ERR_INVALID_STATE; - case ERR_NOT_IMPLEMENTED: return SBI_ERR_NOT_SUPPORTED; - default: return SBI_ERR_FAILED; - } -} - -static struct sbiret make_error(error_t error) { - return (struct sbiret){.error = map_hal_error(error), .value = 0}; -} - -static struct sbiret clock_program_timer(u64 deadline) { +static error_t clock_program_timer(u64 deadline) { error_t err = hal_timer_set_deadline(deadline); if (err != ERR_NONE) { - return make_error(err); + return err; } - return (struct sbiret){.error = SBI_SUCCESS, .value = 0}; + return ERR_NONE; } u64 clock_now(void) { @@ -37,18 +22,18 @@ u64 clock_ticks(void) { return g_ticks; } -struct sbiret clock_rearm(void) { +error_t clock_rearm(void) { if (g_tick_quantum == 0) { - return make_error(ERR_NOT_INITIALIZED); + return ERR_NOT_INITIALIZED; } g_next_deadline = clock_now() + g_tick_quantum; return clock_program_timer(g_next_deadline); } -struct sbiret clock_init(u64 tick_quantum) { +error_t clock_init(u64 tick_quantum) { if (tick_quantum == 0) { - return make_error(ERR_BAD_ARG); + return ERR_BAD_ARG; } g_ticks = 0; @@ -56,13 +41,13 @@ struct sbiret clock_init(u64 tick_quantum) { return clock_rearm(); } -struct sbiret clock_on_timer_interrupt(void) { +error_t clock_on_timer_interrupt(void) { ++g_ticks; error_t err = hal_timer_set_deadline(~0ull); if (err != ERR_NONE) { - return make_error(err); + return err; } - return (struct sbiret){.error = SBI_SUCCESS, .value = 0}; + return ERR_NONE; } From 758875e5b1d7e6e12d3b165665a10a5aa7236aff Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sun, 19 Apr 2026 23:25:16 +0200 Subject: [PATCH 06/22] Run project formatter --- src/example_sbi/entry.c | 2 +- src/lib/hal/arch/riscv/csr_vals.h | 2 +- src/lib/hal/arch/riscv/timer.c | 4 ++-- src/lib/stdbigos/clock.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index e7f650a1..f43ca0f7 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -1,6 +1,6 @@ -#include #include #include +#include #include #include #include diff --git a/src/lib/hal/arch/riscv/csr_vals.h b/src/lib/hal/arch/riscv/csr_vals.h index f422405a..ce7e4939 100644 --- a/src/lib/hal/arch/riscv/csr_vals.h +++ b/src/lib/hal/arch/riscv/csr_vals.h @@ -19,6 +19,6 @@ #define CSR_SSTATUS_UXL_MASK 0b11 #define CSR_SSTATUS_SD (1ul << 63) -#define CSR_SIE_STIE (1ul << 5) +#define CSR_SIE_STIE (1ul << 5) #endif // !HAL_RISCV_CSR_VALS diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index a0324f21..cb784171 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -5,10 +5,10 @@ static error_t map_sbi_error(sbi_error_t err) { switch (err) { - case SBI_SUCCESS: return ERR_NONE; + case SBI_SUCCESS: return ERR_NONE; case SBI_ERR_INVALID_PARAM: return ERR_BAD_ARG; case SBI_ERR_NOT_SUPPORTED: return ERR_NOT_IMPLEMENTED; - default: return ERR_NOT_VALID; + default: return ERR_NOT_VALID; } } diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index a9845dc7..e949fa67 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -1,5 +1,5 @@ -#include #include +#include static u64 g_tick_quantum; static u64 g_next_deadline; From 3ac6a4ea185c79fa440934589ba6c5fadda97d9a Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Mon, 20 Apr 2026 00:41:02 +0200 Subject: [PATCH 07/22] Implement periodic clock and next-switch tick API --- include/stdbigos/clock.h | 10 +++-- src/example_sbi/entry.c | 20 ++++------ src/lib/stdbigos/clock.c | 80 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/include/stdbigos/clock.h b/include/stdbigos/clock.h index b90868ff..216a3782 100644 --- a/include/stdbigos/clock.h +++ b/include/stdbigos/clock.h @@ -9,12 +9,14 @@ /// @ingroup clock /// @{ +error_t clock_init(u64 tick_quantum); + u64 clock_now(void); -u64 clock_ticks(void); +u64 clock_ticks_now(void); -error_t clock_init(u64 tick_quantum); -error_t clock_rearm(void); -error_t clock_on_timer_interrupt(void); +error_t clock_set_next_switch_in(u64 ticks_from_now); +error_t clock_next_switch_tick(u64* out_tick); +error_t clock_ticks_to_next_switch(u64* out_ticks); /// @} /// @} diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index f43ca0f7..cd9584d7 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -9,21 +9,12 @@ static void sbi_puts(const char* str) { while (*str) sbi_debug_console_write_byte(*str++); } -static void timer_handler(void) { - (void)clock_on_timer_interrupt(); -} - void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { if (hal_trap_init() != ERR_NONE) { sbi_puts("trap init failed\n"); return; } - if (hal_trap_register_timer_handler(timer_handler) != ERR_NONE) { - sbi_puts("timer handler register failed\n"); - return; - } - error_t err = clock_init(50000llu); if (err != ERR_NONE) { sbi_puts("clock init failed\n"); @@ -37,9 +28,14 @@ void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { sbi_puts("clock started\n"); - while (clock_ticks() == 0) { + u64 last_tick = clock_ticks_now(); + while (true) { hal_wait_for_interrupt(); - } - sbi_puts("tick one-shot\n"); + u64 now_tick = clock_ticks_now(); + if (now_tick != last_tick) { + sbi_puts("tick periodic\n"); + last_tick = now_tick; + } + } } diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index e949fa67..b85368c1 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -1,9 +1,17 @@ #include +#include #include static u64 g_tick_quantum; static u64 g_next_deadline; static u64 g_ticks; +static u64 g_next_switch_tick; + +static error_t clock_on_timer_interrupt(void); + +static void clock_timer_irq_handler(void) { + (void)clock_on_timer_interrupt(); +} static error_t clock_program_timer(u64 deadline) { error_t err = hal_timer_set_deadline(deadline); @@ -18,11 +26,11 @@ u64 clock_now(void) { return hal_timer_now(); } -u64 clock_ticks(void) { +u64 clock_ticks_now(void) { return g_ticks; } -error_t clock_rearm(void) { +static error_t clock_rearm(void) { if (g_tick_quantum == 0) { return ERR_NOT_INITIALIZED; } @@ -36,18 +44,82 @@ error_t clock_init(u64 tick_quantum) { return ERR_BAD_ARG; } + error_t err = hal_trap_register_timer_handler(clock_timer_irq_handler); + if (err != ERR_NONE) { + return err; + } + g_ticks = 0; g_tick_quantum = tick_quantum; + g_next_switch_tick = 0; return clock_rearm(); } -error_t clock_on_timer_interrupt(void) { +static error_t clock_on_timer_interrupt(void) { ++g_ticks; - error_t err = hal_timer_set_deadline(~0ull); + g_next_deadline += g_tick_quantum; + u64 now = clock_now(); + if (g_next_deadline <= now) { + g_next_deadline = now + g_tick_quantum; + } + + error_t err = clock_program_timer(g_next_deadline); if (err != ERR_NONE) { return err; } return ERR_NONE; } + +error_t clock_set_next_switch_in(u64 ticks_from_now) { + if (g_tick_quantum == 0) { + return ERR_NOT_INITIALIZED; + } + + if (ticks_from_now == 0) { + return ERR_BAD_ARG; + } + + g_next_switch_tick = g_ticks + ticks_from_now; + return ERR_NONE; +} + +error_t clock_next_switch_tick(u64* out_tick) { + if (out_tick == NULL) { + return ERR_BAD_ARG; + } + + if (g_tick_quantum == 0) { + return ERR_NOT_INITIALIZED; + } + + if (g_next_switch_tick == 0) { + return ERR_NOT_FOUND; + } + + *out_tick = g_next_switch_tick; + return ERR_NONE; +} + +error_t clock_ticks_to_next_switch(u64* out_ticks) { + if (out_ticks == NULL) { + return ERR_BAD_ARG; + } + + if (g_tick_quantum == 0) { + return ERR_NOT_INITIALIZED; + } + + if (g_next_switch_tick == 0) { + return ERR_NOT_FOUND; + } + + if (g_ticks >= g_next_switch_tick) { + *out_ticks = 0; + return ERR_NONE; + } + + *out_ticks = g_next_switch_tick - g_ticks; + return ERR_NONE; +} From ac942355256eea96060e2bb842fc18643e8fa9a5 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Mon, 20 Apr 2026 01:05:04 +0200 Subject: [PATCH 08/22] Clean up code --- src/example_sbi/entry.c | 4 +++- src/lib/stdbigos/clock.c | 48 +++++++++++++--------------------------- 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index cd9584d7..8219673a 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -34,7 +34,9 @@ void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { u64 now_tick = clock_ticks_now(); if (now_tick != last_tick) { - sbi_puts("tick periodic\n"); + if ((now_tick % 100) == 0) { + sbi_puts("tick periodic\n"); + } last_tick = now_tick; } } diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index b85368c1..e5f66416 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -7,12 +7,6 @@ static u64 g_next_deadline; static u64 g_ticks; static u64 g_next_switch_tick; -static error_t clock_on_timer_interrupt(void); - -static void clock_timer_irq_handler(void) { - (void)clock_on_timer_interrupt(); -} - static error_t clock_program_timer(u64 deadline) { error_t err = hal_timer_set_deadline(deadline); if (err != ERR_NONE) { @@ -22,15 +16,7 @@ static error_t clock_program_timer(u64 deadline) { return ERR_NONE; } -u64 clock_now(void) { - return hal_timer_now(); -} - -u64 clock_ticks_now(void) { - return g_ticks; -} - -static error_t clock_rearm(void) { +static error_t clock_schedule_next_deadline(void) { if (g_tick_quantum == 0) { return ERR_NOT_INITIALIZED; } @@ -39,6 +25,19 @@ static error_t clock_rearm(void) { return clock_program_timer(g_next_deadline); } +static void clock_timer_irq_handler(void) { + ++g_ticks; + (void)clock_schedule_next_deadline(); +} + +u64 clock_now(void) { + return hal_timer_now(); +} + +u64 clock_ticks_now(void) { + return g_ticks; +} + error_t clock_init(u64 tick_quantum) { if (tick_quantum == 0) { return ERR_BAD_ARG; @@ -52,24 +51,7 @@ error_t clock_init(u64 tick_quantum) { g_ticks = 0; g_tick_quantum = tick_quantum; g_next_switch_tick = 0; - return clock_rearm(); -} - -static error_t clock_on_timer_interrupt(void) { - ++g_ticks; - - g_next_deadline += g_tick_quantum; - u64 now = clock_now(); - if (g_next_deadline <= now) { - g_next_deadline = now + g_tick_quantum; - } - - error_t err = clock_program_timer(g_next_deadline); - if (err != ERR_NONE) { - return err; - } - - return ERR_NONE; + return clock_schedule_next_deadline(); } error_t clock_set_next_switch_in(u64 ticks_from_now) { From 95b19c626403d30a29a03d28273c23c40f4f907f Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Mon, 20 Apr 2026 13:48:27 +0200 Subject: [PATCH 09/22] Enable only timer sie bit and remove unused CSR_SIE_STIE --- src/lib/hal/arch/riscv/csr_vals.h | 2 -- src/lib/hal/arch/riscv/timer.c | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/hal/arch/riscv/csr_vals.h b/src/lib/hal/arch/riscv/csr_vals.h index ce7e4939..0f336d8a 100644 --- a/src/lib/hal/arch/riscv/csr_vals.h +++ b/src/lib/hal/arch/riscv/csr_vals.h @@ -19,6 +19,4 @@ #define CSR_SSTATUS_UXL_MASK 0b11 #define CSR_SSTATUS_SD (1ul << 63) -#define CSR_SIE_STIE (1ul << 5) - #endif // !HAL_RISCV_CSR_VALS diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index cb784171..9a7d86fc 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -2,6 +2,7 @@ #include #include "csr.h" +#include "trap.h" static error_t map_sbi_error(sbi_error_t err) { switch (err) { @@ -38,7 +39,6 @@ error_t hal_timer_arm_relative(u64 delta) { } error_t hal_timer_enable_interrupts(void) { - CSR_SET(sie, CSR_SIE_STIE); - CSR_SET(sstatus, CSR_SSTATUS_SIE); + CSR_SET(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER); return ERR_NONE; } From 26f9eaa4df45d23119b466049baa0a4400a6d94e Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Mon, 20 Apr 2026 14:05:32 +0200 Subject: [PATCH 10/22] Use rdtime pseudoinstruction in hal_timer_now --- src/lib/hal/arch/riscv/timer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index 9a7d86fc..12c2f15f 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -14,7 +14,9 @@ static error_t map_sbi_error(sbi_error_t err) { } u64 hal_timer_now(void) { - return CSR_READ(time); + u64 now; + __asm__ volatile("rdtime %0" : "=r"(now)::"memory"); + return now; } error_t hal_timer_set_deadline(u64 deadline) { From 68caca4a4222ea0b01d1178d318f7f26eb3f7866 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 19:35:46 +0200 Subject: [PATCH 11/22] Rename for consistency --- include/hal/timer.h | 2 +- src/lib/hal/arch/riscv/timer.c | 4 ++-- src/lib/stdbigos/clock.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/hal/timer.h b/include/hal/timer.h index b345cc3b..2947958e 100644 --- a/include/hal/timer.h +++ b/include/hal/timer.h @@ -23,7 +23,7 @@ u64 hal_timer_now(void); * @retval ERR_NOT_IMPLEMENTED Timer SBI extension unsupported * @retval ERR_NOT_VALID Other platform/firmware failure */ -error_t hal_timer_set_deadline(u64 deadline); +error_t hal_timer_arm_absolute(u64 deadline); /** * @brief Program next timer interrupt relative to current time. diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index 12c2f15f..df8ca118 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -19,7 +19,7 @@ u64 hal_timer_now(void) { return now; } -error_t hal_timer_set_deadline(u64 deadline) { +error_t hal_timer_arm_absolute(u64 deadline) { if (deadline == 0) { return ERR_BAD_ARG; } @@ -37,7 +37,7 @@ error_t hal_timer_arm_relative(u64 delta) { return ERR_BAD_ARG; } - return hal_timer_set_deadline(hal_timer_now() + delta); + return hal_timer_arm_absolute(hal_timer_now() + delta); } error_t hal_timer_enable_interrupts(void) { diff --git a/src/lib/stdbigos/clock.c b/src/lib/stdbigos/clock.c index e5f66416..a64273957d 100644 --- a/src/lib/stdbigos/clock.c +++ b/src/lib/stdbigos/clock.c @@ -8,7 +8,7 @@ static u64 g_ticks; static u64 g_next_switch_tick; static error_t clock_program_timer(u64 deadline) { - error_t err = hal_timer_set_deadline(deadline); + error_t err = hal_timer_arm_absolute(deadline); if (err != ERR_NONE) { return err; } From 9bc736914c90d68d21bca83b74aaa80004655121 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 23:02:36 +0200 Subject: [PATCH 12/22] Move sbi_error_t to error_t mapping function to common util file Co-authored-by: Copilot --- include/stdbigos/sbi_utils.h | 16 ++++++++++++++++ src/lib/hal/arch/riscv/timer.c | 12 ++---------- 2 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 include/stdbigos/sbi_utils.h diff --git a/include/stdbigos/sbi_utils.h b/include/stdbigos/sbi_utils.h new file mode 100644 index 00000000..ddca4fd9 --- /dev/null +++ b/include/stdbigos/sbi_utils.h @@ -0,0 +1,16 @@ +#ifndef _STDBIGOS_SBI_UTILS_H_ +#define _STDBIGOS_SBI_UTILS_H_ + +#include "error.h" +#include "sbi.h" + +static inline error_t sbi_map_error(sbi_error_t err) { + switch (err) { + case SBI_SUCCESS: return ERR_NONE; + case SBI_ERR_INVALID_PARAM: return ERR_BAD_ARG; + case SBI_ERR_NOT_SUPPORTED: return ERR_NOT_IMPLEMENTED; + default: return ERR_NOT_VALID; + } +} + +#endif // !_STDBIGOS_SBI_UTILS_H_ \ No newline at end of file diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index df8ca118..2841064a 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -1,18 +1,10 @@ #include #include +#include #include "csr.h" #include "trap.h" -static error_t map_sbi_error(sbi_error_t err) { - switch (err) { - case SBI_SUCCESS: return ERR_NONE; - case SBI_ERR_INVALID_PARAM: return ERR_BAD_ARG; - case SBI_ERR_NOT_SUPPORTED: return ERR_NOT_IMPLEMENTED; - default: return ERR_NOT_VALID; - } -} - u64 hal_timer_now(void) { u64 now; __asm__ volatile("rdtime %0" : "=r"(now)::"memory"); @@ -29,7 +21,7 @@ error_t hal_timer_arm_absolute(u64 deadline) { ret = sbi_legacy_set_timer(deadline); } - return map_sbi_error(ret.error); + return sbi_map_error(ret.error); } error_t hal_timer_arm_relative(u64 delta) { From 747c60703683285c1a442388bfe39d703b8ba11e Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 23:13:08 +0200 Subject: [PATCH 13/22] Adjust returns in timer Co-authored-by: Copilot --- include/hal/timer.h | 3 ++- src/example_sbi/entry.c | 5 +---- src/lib/hal/arch/riscv/timer.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/hal/timer.h b/include/hal/timer.h index 2947958e..e57aaa37 100644 --- a/include/hal/timer.h +++ b/include/hal/timer.h @@ -11,6 +11,7 @@ /** * @brief Read current monotonic hardware timer value. + * @return Current hardware timer tick value. */ u64 hal_timer_now(void); @@ -39,7 +40,7 @@ error_t hal_timer_arm_relative(u64 delta); /** * @brief Enable supervisor timer interrupts and global supervisor IRQs. */ -error_t hal_timer_enable_interrupts(void); +void hal_timer_enable_interrupts(void); /// @} diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index 8219673a..c53e0a5e 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -21,10 +21,7 @@ void main([[maybe_unused]] u32 hartid, [[maybe_unused]] const void* fdt) { return; } - if (hal_timer_enable_interrupts() != ERR_NONE) { - sbi_puts("timer irq enable failed\n"); - return; - } + hal_timer_enable_interrupts(); sbi_puts("clock started\n"); diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index 2841064a..77ac0c0a 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -32,7 +32,6 @@ error_t hal_timer_arm_relative(u64 delta) { return hal_timer_arm_absolute(hal_timer_now() + delta); } -error_t hal_timer_enable_interrupts(void) { +void hal_timer_enable_interrupts(void) { CSR_SET(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER); - return ERR_NONE; } From ce4eafd911baa16680b9a65a9ee506768dd2a8af Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 23:29:55 +0200 Subject: [PATCH 14/22] Add option to disable timer interrupts --- include/hal/timer.h | 7 ++++++- src/lib/hal/arch/riscv/timer.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/hal/timer.h b/include/hal/timer.h index e57aaa37..f64b1809 100644 --- a/include/hal/timer.h +++ b/include/hal/timer.h @@ -38,10 +38,15 @@ error_t hal_timer_arm_absolute(u64 deadline); error_t hal_timer_arm_relative(u64 delta); /** - * @brief Enable supervisor timer interrupts and global supervisor IRQs. + * @brief Enable supervisor timer interrupts. */ void hal_timer_enable_interrupts(void); +/** + * @brief Disable supervisor timer interrupts. + */ +void hal_timer_disable_interrupts(void); + /// @} #endif // !HAL_TIMER_H diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index 77ac0c0a..befc0cac 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -35,3 +35,7 @@ error_t hal_timer_arm_relative(u64 delta) { void hal_timer_enable_interrupts(void) { CSR_SET(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER); } + +void hal_timer_disable_interrupts(void) { + CSR_CLEAR(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER); +} From 37ce35922f5b398e98f96da94b08411a32a7de22 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 23:30:39 +0200 Subject: [PATCH 15/22] Remove redundant include --- src/example_sbi/entry.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index c53e0a5e..7d9c95c3 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -3,7 +3,6 @@ #include #include #include -#include static void sbi_puts(const char* str) { while (*str) sbi_debug_console_write_byte(*str++); From a0d61d58a68d3086f91f0789efb0d1fd55a4e59e Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sun, 26 Apr 2026 23:30:07 +0200 Subject: [PATCH 16/22] Fix formatting --- include/hal/timer.h | 2 +- include/stdbigos/sbi_utils.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/hal/timer.h b/include/hal/timer.h index f64b1809..bc790984 100644 --- a/include/hal/timer.h +++ b/include/hal/timer.h @@ -43,7 +43,7 @@ error_t hal_timer_arm_relative(u64 delta); void hal_timer_enable_interrupts(void); /** - * @brief Disable supervisor timer interrupts. + * @brief Disable supervisor timer interrupts. */ void hal_timer_disable_interrupts(void); diff --git a/include/stdbigos/sbi_utils.h b/include/stdbigos/sbi_utils.h index ddca4fd9..9b8ef191 100644 --- a/include/stdbigos/sbi_utils.h +++ b/include/stdbigos/sbi_utils.h @@ -13,4 +13,4 @@ static inline error_t sbi_map_error(sbi_error_t err) { } } -#endif // !_STDBIGOS_SBI_UTILS_H_ \ No newline at end of file +#endif // !_STDBIGOS_SBI_UTILS_H_ From abed4ac31e5672666ab6fed91c5f0251af6f53af Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 23:29:55 +0200 Subject: [PATCH 17/22] Add option to disable timer interrupts --- include/hal/timer.h | 7 ++++++- src/lib/hal/arch/riscv/timer.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/hal/timer.h b/include/hal/timer.h index e57aaa37..bc790984 100644 --- a/include/hal/timer.h +++ b/include/hal/timer.h @@ -38,10 +38,15 @@ error_t hal_timer_arm_absolute(u64 deadline); error_t hal_timer_arm_relative(u64 delta); /** - * @brief Enable supervisor timer interrupts and global supervisor IRQs. + * @brief Enable supervisor timer interrupts. */ void hal_timer_enable_interrupts(void); +/** + * @brief Disable supervisor timer interrupts. + */ +void hal_timer_disable_interrupts(void); + /// @} #endif // !HAL_TIMER_H diff --git a/src/lib/hal/arch/riscv/timer.c b/src/lib/hal/arch/riscv/timer.c index 77ac0c0a..befc0cac 100644 --- a/src/lib/hal/arch/riscv/timer.c +++ b/src/lib/hal/arch/riscv/timer.c @@ -35,3 +35,7 @@ error_t hal_timer_arm_relative(u64 delta) { void hal_timer_enable_interrupts(void) { CSR_SET(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER); } + +void hal_timer_disable_interrupts(void) { + CSR_CLEAR(sie, 1ul << HAL_RISCV_TRAP_INT_S_TIMER); +} From 62295a999e8e6085439567ddd65269dcda6e1e4a Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Fri, 24 Apr 2026 23:30:39 +0200 Subject: [PATCH 18/22] Remove redundant include --- src/example_sbi/entry.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/example_sbi/entry.c b/src/example_sbi/entry.c index c53e0a5e..7d9c95c3 100644 --- a/src/example_sbi/entry.c +++ b/src/example_sbi/entry.c @@ -3,7 +3,6 @@ #include #include #include -#include static void sbi_puts(const char* str) { while (*str) sbi_debug_console_write_byte(*str++); From 1becde77bad8c7a0a9a4556283f5ce457e21007a Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sun, 26 Apr 2026 23:30:07 +0200 Subject: [PATCH 19/22] Fix formatting --- include/stdbigos/sbi_utils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/stdbigos/sbi_utils.h b/include/stdbigos/sbi_utils.h index ddca4fd9..9b8ef191 100644 --- a/include/stdbigos/sbi_utils.h +++ b/include/stdbigos/sbi_utils.h @@ -13,4 +13,4 @@ static inline error_t sbi_map_error(sbi_error_t err) { } } -#endif // !_STDBIGOS_SBI_UTILS_H_ \ No newline at end of file +#endif // !_STDBIGOS_SBI_UTILS_H_ From 3ff6e4cc30514fde0c1002fb5927cb3eafd7dff9 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sat, 2 May 2026 21:59:45 +0200 Subject: [PATCH 20/22] Enhance documentation for clock API in clock.h --- include/stdbigos/clock.h | 79 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/include/stdbigos/clock.h b/include/stdbigos/clock.h index 216a3782..b018fdec 100644 --- a/include/stdbigos/clock.h +++ b/include/stdbigos/clock.h @@ -4,21 +4,88 @@ #include "error.h" #include "types.h" -/// @ingroup stdbigos -/// @{ -/// @ingroup clock -/// @{ +/** + * @file include/stdbigos/clock.h + * @brief Public periodic clock API used by the scheduler and examples. + * + * The periodic clock provides a monotonic time source measured in + * architecture-specific ticks and supports scheduling a "next switch" + * tick for the scheduler to observe. + * + * @ingroup stdbigos + * @{ + * @ingroup clock + * @{ + */ +/** + * @brief Initialize the periodic clock subsystem. + * + * Initialize internal state and program the first timer deadline using + * the provided tick quantum. + * + * @param tick_quantum Number of hardware timer ticks per software tick. + * @return error_t E_OK on success, otherwise an error code. + */ error_t clock_init(u64 tick_quantum); +/** + * @brief Return the current time in hardware timer ticks. + * + * This returns a monotonic timestamp suitable for computing deadlines. + * + * @return Current time in hardware ticks. + */ u64 clock_now(void); + +/** + * @brief Return the number of software ticks since boot. + * + * Software ticks are incremented by the timer IRQ handler and advance + * at a rate of one per `tick_quantum` hardware ticks. + * + * @return Number of elapsed software ticks. + */ u64 clock_ticks_now(void); +/** + * @brief Request the scheduler be woken in a number of software ticks. + * + * Programs the next switch tick to be `ticks_from_now` software ticks + * in the future. This does not block; use `clock_next_switch_tick` + * or `clock_ticks_to_next_switch` to query the scheduled value. + * + * @param ticks_from_now Number of software ticks from now to schedule. + * @return error_t E_OK on success, otherwise an error code. + */ error_t clock_set_next_switch_in(u64 ticks_from_now); + +/** + * @brief Obtain the currently scheduled next-switch absolute tick. + * + * Writes the absolute software tick value at which the scheduler has + * requested a switch into `out_tick`. + * + * @param out_tick Pointer to u64 to receive the absolute tick value. + * @return error_t E_OK on success, EINVAL if `out_tick` is NULL, or + * other error codes on failure. + */ error_t clock_next_switch_tick(u64* out_tick); + +/** + * @brief Obtain the number of software ticks until the next switch. + * + * Writes into `out_ticks` the number of ticks remaining until the + * scheduled next-switch tick. If a next-switch is not scheduled, + * behavior is implementation-defined. + * + * @param out_ticks Pointer to u64 to receive remaining ticks. + * @return error_t E_OK on success, EINVAL if `out_ticks` is NULL, or + * other error codes on failure. + */ error_t clock_ticks_to_next_switch(u64* out_ticks); -/// @} -/// @} +/** @} */ /* end group clock */ +/** @} */ /* end group stdbigos */ #endif // !STDBIGOS_CLOCK From 5769ac9d418d621a1c1761ff6d453db5e47e7169 Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sat, 2 May 2026 23:10:24 +0200 Subject: [PATCH 21/22] Add clock API documentation and update group annotations in header Co-authored-by: Copilot --- docs/source/pages/api/libs/stdbigos/clock.rst | 5 +++++ docs/source/pages/api/libs/stdbigos/index.rst | 1 + include/stdbigos/clock.h | 4 ++-- 3 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 docs/source/pages/api/libs/stdbigos/clock.rst diff --git a/docs/source/pages/api/libs/stdbigos/clock.rst b/docs/source/pages/api/libs/stdbigos/clock.rst new file mode 100644 index 00000000..9342f674 --- /dev/null +++ b/docs/source/pages/api/libs/stdbigos/clock.rst @@ -0,0 +1,5 @@ +===== +Clock +===== + +.. doxygengroup:: clock diff --git a/docs/source/pages/api/libs/stdbigos/index.rst b/docs/source/pages/api/libs/stdbigos/index.rst index 94ba6004..8d51e59e 100644 --- a/docs/source/pages/api/libs/stdbigos/index.rst +++ b/docs/source/pages/api/libs/stdbigos/index.rst @@ -10,3 +10,4 @@ Stdbigos types string bitutils + clock diff --git a/include/stdbigos/clock.h b/include/stdbigos/clock.h index b018fdec..11152ea4 100644 --- a/include/stdbigos/clock.h +++ b/include/stdbigos/clock.h @@ -12,9 +12,9 @@ * architecture-specific ticks and supports scheduling a "next switch" * tick for the scheduler to observe. * - * @ingroup stdbigos + * @addtogroup stdbigos * @{ - * @ingroup clock + * @addtogroup clock * @{ */ From 5b5bdf27c2af30c820d043227e957fad6057328f Mon Sep 17 00:00:00 2001 From: Grzegorz Suwaj Date: Sat, 2 May 2026 23:11:38 +0200 Subject: [PATCH 22/22] Fix formatting of the clock.h header guard --- include/stdbigos/clock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/stdbigos/clock.h b/include/stdbigos/clock.h index 11152ea4..87fdd536 100644 --- a/include/stdbigos/clock.h +++ b/include/stdbigos/clock.h @@ -88,4 +88,4 @@ error_t clock_ticks_to_next_switch(u64* out_ticks); /** @} */ /* end group clock */ /** @} */ /* end group stdbigos */ -#endif // !STDBIGOS_CLOCK +#endif // !STDBIGOS_CLOCK