From 20663b533b3f0e48bec423066cd46cbc3db9be66 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 30 Jun 2026 20:02:24 +0300 Subject: [PATCH] Kernel: Rework sleeping API instead of sleep_{ns,ms} we now have sleep_{for,until}_{ns,ms}. This makes code cleaner that just wants to sleep until some timestamp --- kernel/include/kernel/Thread.h | 14 ++++++++++---- kernel/include/kernel/Timer/Timer.h | 15 +++++++++++++-- kernel/kernel/ACPI/ACPI.cpp | 2 +- kernel/kernel/ACPI/AML/Node.cpp | 12 ++++++------ kernel/kernel/Audio/HDAudio/Controller.cpp | 2 +- kernel/kernel/FS/DevFS/FileSystem.cpp | 4 +++- kernel/kernel/FS/VirtualFileSystem.cpp | 2 +- kernel/kernel/Process.cpp | 4 ++-- kernel/kernel/Storage/ATA/ATABus.cpp | 6 +++--- kernel/kernel/Thread.cpp | 14 ++++++++++++-- kernel/kernel/Timer/Timer.cpp | 13 ++++++++++--- 11 files changed, 62 insertions(+), 26 deletions(-) diff --git a/kernel/include/kernel/Thread.h b/kernel/include/kernel/Thread.h index 35bb1189..21aa6294 100644 --- a/kernel/include/kernel/Thread.h +++ b/kernel/include/kernel/Thread.h @@ -77,15 +77,21 @@ namespace Kernel // blocks current thread and returns either on unblock, eintr, spuriously or after timeout // if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake - BAN::ErrorOr sleep_or_eintr_ns(uint64_t ns); + BAN::ErrorOr sleep_or_eintr_for_ns(uint64_t timeout_ns); + BAN::ErrorOr sleep_or_eintr_until_ns(uint64_t waketime_ns); BAN::ErrorOr block_or_eintr_indefinite(ThreadBlocker& thread_blocker, BaseMutex* mutex); BAN::ErrorOr block_or_eintr_or_timeout_ns(ThreadBlocker& thread_blocker, uint64_t timeout_ns, bool etimedout, BaseMutex* mutex); BAN::ErrorOr block_or_eintr_or_waketime_ns(ThreadBlocker& thread_blocker, uint64_t wake_time_ns, bool etimedout, BaseMutex* mutex); - BAN::ErrorOr sleep_or_eintr_ms(uint64_t ms) + BAN::ErrorOr sleep_or_eintr_for_ms(uint64_t timeout_ms) { - ASSERT(!BAN::Math::will_multiplication_overflow(ms, 1'000'000)); - return sleep_or_eintr_ns(ms * 1'000'000); + ASSERT(!BAN::Math::will_multiplication_overflow(timeout_ms, 1'000'000)); + return sleep_or_eintr_for_ns(timeout_ms * 1'000'000); + } + BAN::ErrorOr sleep_or_eintr_until_ms(uint64_t waketime_ms) + { + ASSERT(!BAN::Math::will_multiplication_overflow(waketime_ms, 1'000'000)); + return sleep_or_eintr_until_ns(waketime_ms * 1'000'000); } BAN::ErrorOr block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout, BaseMutex* mutex) { diff --git a/kernel/include/kernel/Timer/Timer.h b/kernel/include/kernel/Timer/Timer.h index 62f997d5..fbc8db31 100644 --- a/kernel/include/kernel/Timer/Timer.h +++ b/kernel/include/kernel/Timer/Timer.h @@ -52,8 +52,19 @@ namespace Kernel virtual bool pre_scheduler_sleep_needs_lock() const override; virtual void pre_scheduler_sleep_ns(uint64_t) override; - void sleep_ms(uint64_t ms) const { ASSERT(!BAN::Math::will_multiplication_overflow(ms, 1'000'000)); return sleep_ns(ms * 1'000'000); } - void sleep_ns(uint64_t ns) const; + void sleep_for_ns(uint64_t timeout_ns) const; + void sleep_until_ns(uint64_t waketime_ns) const; + + void sleep_for_ms(uint64_t timeout_ms) const + { + ASSERT(!BAN::Math::will_multiplication_overflow(timeout_ms, 1'000'000)); + return sleep_for_ns(timeout_ms * 1'000'000); + } + void sleep_until_ms(uint64_t waketime_ms) const + { + ASSERT(!BAN::Math::will_multiplication_overflow(waketime_ms, 1'000'000)); + return sleep_until_ns(waketime_ms * 1'000'000); + } void dont_invoke_scheduler() { m_timer->m_should_invoke_scheduler = false; } diff --git a/kernel/kernel/ACPI/ACPI.cpp b/kernel/kernel/ACPI/ACPI.cpp index 86e9a171..8088f890 100644 --- a/kernel/kernel/ACPI/ACPI.cpp +++ b/kernel/kernel/ACPI/ACPI.cpp @@ -952,7 +952,7 @@ acpi_release_global_lock: { if (IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN) break; - SystemTimer::get().sleep_ms(10); + SystemTimer::get().sleep_for_ms(10); } if (!(IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN)) diff --git a/kernel/kernel/ACPI/AML/Node.cpp b/kernel/kernel/ACPI/AML/Node.cpp index fc6f7ed9..b3e6bf4a 100644 --- a/kernel/kernel/ACPI/AML/Node.cpp +++ b/kernel/kernel/ACPI/AML/Node.cpp @@ -2146,9 +2146,9 @@ namespace Kernel::ACPI::AML auto milliseconds = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t))); - const uint64_t wakeup_ms = SystemTimer::get().ms_since_boot() + milliseconds.as.integer.value; - for (uint64_t curr_ms = SystemTimer::get().ms_since_boot(); curr_ms < wakeup_ms; curr_ms = SystemTimer::get().ms_since_boot()) - SystemTimer::get().sleep_ms(wakeup_ms - curr_ms); + const uint64_t waketime_ms = SystemTimer::get().ms_since_boot() + milliseconds.as.integer.value; + while (SystemTimer::get().ms_since_boot() < waketime_ms) + SystemTimer::get().sleep_until_ms(waketime_ms); return {}; } @@ -2392,7 +2392,7 @@ namespace Kernel::ACPI::AML result.type = Node::Type::Integer; result.as.integer.value = BAN::numeric_limits::max(); - const uint64_t wake_time_ms = (timeout_ms >= 0xFFFF) + const uint64_t waketime_ms = (timeout_ms >= 0xFFFF) ? BAN::numeric_limits::max() : SystemTimer::get().ms_since_boot() + timeout_ms; @@ -2401,9 +2401,9 @@ namespace Kernel::ACPI::AML { if (sync_object->node.as.mutex->mutex.try_lock()) break; - if (SystemTimer::get().ms_since_boot() >= wake_time_ms) + if (SystemTimer::get().ms_since_boot() >= waketime_ms) return result; - SystemTimer::get().sleep_ms(1); + Processor::yield(); } if (sync_object->node.as.mutex->global_lock) diff --git a/kernel/kernel/Audio/HDAudio/Controller.cpp b/kernel/kernel/Audio/HDAudio/Controller.cpp index 07214529..beab5511 100644 --- a/kernel/kernel/Audio/HDAudio/Controller.cpp +++ b/kernel/kernel/Audio/HDAudio/Controller.cpp @@ -113,7 +113,7 @@ namespace Kernel // 4.3 The software must wait at least 521 us (25 frames) after reading CRST as a 1 // before assuming that codecs have all made status change requests and have been // registered by the controller - SystemTimer::get().sleep_ms(1); + SystemTimer::get().sleep_for_ns(521'000); return {}; } diff --git a/kernel/kernel/FS/DevFS/FileSystem.cpp b/kernel/kernel/FS/DevFS/FileSystem.cpp index 4efe161e..11926ca4 100644 --- a/kernel/kernel/FS/DevFS/FileSystem.cpp +++ b/kernel/kernel/FS/DevFS/FileSystem.cpp @@ -50,6 +50,7 @@ namespace Kernel [](void* _devfs) { auto* devfs = static_cast(_devfs); + uint64_t next_update_ms = SystemTimer::get().ms_since_boot(); while (true) { { @@ -57,7 +58,8 @@ namespace Kernel for (auto& device : devfs->m_devices) device->update(); } - SystemTimer::get().sleep_ms(10); + SystemTimer::get().sleep_until_ms(next_update_ms); + next_update_ms += 10; } }, s_instance )); diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index a721274a..c54affa9 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -157,7 +157,7 @@ namespace Kernel if (i == 4) dwarnln("Could not find specified root device, waiting for it to get loaded..."); - SystemTimer::get().sleep_ms(sleep_ms); + SystemTimer::get().sleep_for_ms(sleep_ms); } derrorln("Could not find root device '{}' after {} ms", root_path, timeout_ms); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 6fbb55ab..5ee37c73 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1048,7 +1048,7 @@ namespace Kernel const uint64_t current_ms = SystemTimer::get().ms_since_boot(); if (current_ms >= wake_time_ms) break; - SystemTimer::get().sleep_ms(wake_time_ms - current_ms); + SystemTimer::get().sleep_until_ms(wake_time_ms); } const uint64_t current_ms = SystemTimer::get().ms_since_boot(); @@ -1070,7 +1070,7 @@ namespace Kernel return 0; const uint64_t wake_time_ns = SystemTimer::get().ns_since_boot() + sleep_ns; - SystemTimer::get().sleep_ns(sleep_ns); + SystemTimer::get().sleep_until_ns(wake_time_ns); const uint64_t current_ns = SystemTimer::get().ns_since_boot(); if (current_ns < wake_time_ns) diff --git a/kernel/kernel/Storage/ATA/ATABus.cpp b/kernel/kernel/Storage/ATA/ATABus.cpp index cc8771ca..ee0177ba 100644 --- a/kernel/kernel/Storage/ATA/ATABus.cpp +++ b/kernel/kernel/Storage/ATA/ATABus.cpp @@ -66,7 +66,7 @@ namespace Kernel static void select_delay() { - SystemTimer::get().sleep_ns(400); + SystemTimer::get().sleep_for_ns(400); } void ATABus::select_device(bool is_secondary) @@ -87,7 +87,7 @@ namespace Kernel io_write(ATA_PORT_LBA1, 0); io_write(ATA_PORT_LBA2, 0); io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY); - SystemTimer::get().sleep_ms(1); + SystemTimer::get().sleep_for_ms(1); // No device on port if (io_read(ATA_PORT_STATUS) == 0) @@ -112,7 +112,7 @@ namespace Kernel } io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET); - SystemTimer::get().sleep_ms(1); + SystemTimer::get().sleep_for_ms(1); } TRY(wait(true)); diff --git a/kernel/kernel/Thread.cpp b/kernel/kernel/Thread.cpp index cbf6a70e..abbfc563 100644 --- a/kernel/kernel/Thread.cpp +++ b/kernel/kernel/Thread.cpp @@ -863,11 +863,21 @@ namespace Kernel return {}; } - BAN::ErrorOr Thread::sleep_or_eintr_ns(uint64_t ns) + BAN::ErrorOr Thread::sleep_or_eintr_for_ns(uint64_t timeout_ns) { if (is_interrupted_by_signal(true)) return BAN::Error::from_errno(EINTR); - SystemTimer::get().sleep_ns(ns); + SystemTimer::get().sleep_for_ns(timeout_ns); + if (is_interrupted_by_signal(true)) + return BAN::Error::from_errno(EINTR); + return {}; + } + + BAN::ErrorOr Thread::sleep_or_eintr_until_ns(uint64_t waketime_ns) + { + if (is_interrupted_by_signal(true)) + return BAN::Error::from_errno(EINTR); + SystemTimer::get().sleep_until_ns(waketime_ns); if (is_interrupted_by_signal(true)) return BAN::Error::from_errno(EINTR); return {}; diff --git a/kernel/kernel/Timer/Timer.cpp b/kernel/kernel/Timer/Timer.cpp index 0b0e6646..dffbfefc 100644 --- a/kernel/kernel/Timer/Timer.cpp +++ b/kernel/kernel/Timer/Timer.cpp @@ -229,11 +229,18 @@ namespace Kernel return m_timer->pre_scheduler_sleep_ns(ns); } - void SystemTimer::sleep_ns(uint64_t ns) const + void SystemTimer::sleep_for_ns(uint64_t timeout_ns) const { - if (ns == 0) + const uint64_t base_ns = ns_since_boot(); + ASSERT(!BAN::Math::will_addition_overflow(base_ns, timeout_ns)); + Processor::scheduler().block_current_thread(nullptr, base_ns + timeout_ns, nullptr); + } + + void SystemTimer::sleep_until_ns(uint64_t waketime_ns) const + { + if (ns_since_boot() >= waketime_ns) return; - Processor::scheduler().block_current_thread(nullptr, ns_since_boot() + ns, nullptr); + Processor::scheduler().block_current_thread(nullptr, waketime_ns, nullptr); } timespec SystemTimer::real_time() const