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
This commit is contained in:
2026-06-30 20:02:24 +03:00
parent 6f002f0c07
commit 20663b533b
11 changed files with 62 additions and 26 deletions

View File

@@ -77,15 +77,21 @@ namespace Kernel
// blocks current thread and returns either on unblock, eintr, spuriously or after timeout // 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 // if mutex is not nullptr, it will be atomically freed before blocking and automatically locked on wake
BAN::ErrorOr<void> sleep_or_eintr_ns(uint64_t ns); BAN::ErrorOr<void> sleep_or_eintr_for_ns(uint64_t timeout_ns);
BAN::ErrorOr<void> sleep_or_eintr_until_ns(uint64_t waketime_ns);
BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker, BaseMutex* mutex); BAN::ErrorOr<void> block_or_eintr_indefinite(ThreadBlocker& thread_blocker, BaseMutex* mutex);
BAN::ErrorOr<void> block_or_eintr_or_timeout_ns(ThreadBlocker& thread_blocker, uint64_t timeout_ns, bool etimedout, BaseMutex* mutex); BAN::ErrorOr<void> block_or_eintr_or_timeout_ns(ThreadBlocker& thread_blocker, uint64_t timeout_ns, bool etimedout, BaseMutex* mutex);
BAN::ErrorOr<void> block_or_eintr_or_waketime_ns(ThreadBlocker& thread_blocker, uint64_t wake_time_ns, bool etimedout, BaseMutex* mutex); BAN::ErrorOr<void> block_or_eintr_or_waketime_ns(ThreadBlocker& thread_blocker, uint64_t wake_time_ns, bool etimedout, BaseMutex* mutex);
BAN::ErrorOr<void> sleep_or_eintr_ms(uint64_t ms) BAN::ErrorOr<void> sleep_or_eintr_for_ms(uint64_t timeout_ms)
{ {
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000)); ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_ms, 1'000'000));
return sleep_or_eintr_ns(ms * 1'000'000); return sleep_or_eintr_for_ns(timeout_ms * 1'000'000);
}
BAN::ErrorOr<void> sleep_or_eintr_until_ms(uint64_t waketime_ms)
{
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(waketime_ms, 1'000'000));
return sleep_or_eintr_until_ns(waketime_ms * 1'000'000);
} }
BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout, BaseMutex* mutex) BAN::ErrorOr<void> block_or_eintr_or_timeout_ms(ThreadBlocker& thread_blocker, uint64_t timeout_ms, bool etimedout, BaseMutex* mutex)
{ {

View File

@@ -52,8 +52,19 @@ namespace Kernel
virtual bool pre_scheduler_sleep_needs_lock() const override; virtual bool pre_scheduler_sleep_needs_lock() const override;
virtual void pre_scheduler_sleep_ns(uint64_t) override; virtual void pre_scheduler_sleep_ns(uint64_t) override;
void sleep_ms(uint64_t ms) const { ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(ms, 1'000'000)); return sleep_ns(ms * 1'000'000); } void sleep_for_ns(uint64_t timeout_ns) const;
void sleep_ns(uint64_t 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<uint64_t>(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<uint64_t>(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; } void dont_invoke_scheduler() { m_timer->m_should_invoke_scheduler = false; }

View File

@@ -952,7 +952,7 @@ acpi_release_global_lock:
{ {
if (IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN) if (IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN)
break; break;
SystemTimer::get().sleep_ms(10); SystemTimer::get().sleep_for_ms(10);
} }
if (!(IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN)) if (!(IO::inw(fadt().pm1a_cnt_blk) & PM1_CNT_SCI_EN))

View File

@@ -2146,9 +2146,9 @@ namespace Kernel::ACPI::AML
auto milliseconds = TRY(convert_node(TRY(parse_node(context)), ConvInteger, sizeof(uint64_t))); 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; const uint64_t waketime_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()) while (SystemTimer::get().ms_since_boot() < waketime_ms)
SystemTimer::get().sleep_ms(wakeup_ms - curr_ms); SystemTimer::get().sleep_until_ms(waketime_ms);
return {}; return {};
} }
@@ -2392,7 +2392,7 @@ namespace Kernel::ACPI::AML
result.type = Node::Type::Integer; result.type = Node::Type::Integer;
result.as.integer.value = BAN::numeric_limits<uint64_t>::max(); result.as.integer.value = BAN::numeric_limits<uint64_t>::max();
const uint64_t wake_time_ms = (timeout_ms >= 0xFFFF) const uint64_t waketime_ms = (timeout_ms >= 0xFFFF)
? BAN::numeric_limits<uint64_t>::max() ? BAN::numeric_limits<uint64_t>::max()
: SystemTimer::get().ms_since_boot() + timeout_ms; : SystemTimer::get().ms_since_boot() + timeout_ms;
@@ -2401,9 +2401,9 @@ namespace Kernel::ACPI::AML
{ {
if (sync_object->node.as.mutex->mutex.try_lock()) if (sync_object->node.as.mutex->mutex.try_lock())
break; break;
if (SystemTimer::get().ms_since_boot() >= wake_time_ms) if (SystemTimer::get().ms_since_boot() >= waketime_ms)
return result; return result;
SystemTimer::get().sleep_ms(1); Processor::yield();
} }
if (sync_object->node.as.mutex->global_lock) if (sync_object->node.as.mutex->global_lock)

View File

@@ -113,7 +113,7 @@ namespace Kernel
// 4.3 The software must wait at least 521 us (25 frames) after reading CRST as a 1 // 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 // before assuming that codecs have all made status change requests and have been
// registered by the controller // registered by the controller
SystemTimer::get().sleep_ms(1); SystemTimer::get().sleep_for_ns(521'000);
return {}; return {};
} }

View File

@@ -50,6 +50,7 @@ namespace Kernel
[](void* _devfs) [](void* _devfs)
{ {
auto* devfs = static_cast<DevFileSystem*>(_devfs); auto* devfs = static_cast<DevFileSystem*>(_devfs);
uint64_t next_update_ms = SystemTimer::get().ms_since_boot();
while (true) while (true)
{ {
{ {
@@ -57,7 +58,8 @@ namespace Kernel
for (auto& device : devfs->m_devices) for (auto& device : devfs->m_devices)
device->update(); device->update();
} }
SystemTimer::get().sleep_ms(10); SystemTimer::get().sleep_until_ms(next_update_ms);
next_update_ms += 10;
} }
}, s_instance }, s_instance
)); ));

View File

@@ -157,7 +157,7 @@ namespace Kernel
if (i == 4) if (i == 4)
dwarnln("Could not find specified root device, waiting for it to get loaded..."); 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); derrorln("Could not find root device '{}' after {} ms", root_path, timeout_ms);

View File

@@ -1048,7 +1048,7 @@ namespace Kernel
const uint64_t current_ms = SystemTimer::get().ms_since_boot(); const uint64_t current_ms = SystemTimer::get().ms_since_boot();
if (current_ms >= wake_time_ms) if (current_ms >= wake_time_ms)
break; 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(); const uint64_t current_ms = SystemTimer::get().ms_since_boot();
@@ -1070,7 +1070,7 @@ namespace Kernel
return 0; return 0;
const uint64_t wake_time_ns = SystemTimer::get().ns_since_boot() + sleep_ns; 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(); const uint64_t current_ns = SystemTimer::get().ns_since_boot();
if (current_ns < wake_time_ns) if (current_ns < wake_time_ns)

View File

@@ -66,7 +66,7 @@ namespace Kernel
static void select_delay() static void select_delay()
{ {
SystemTimer::get().sleep_ns(400); SystemTimer::get().sleep_for_ns(400);
} }
void ATABus::select_device(bool is_secondary) void ATABus::select_device(bool is_secondary)
@@ -87,7 +87,7 @@ namespace Kernel
io_write(ATA_PORT_LBA1, 0); io_write(ATA_PORT_LBA1, 0);
io_write(ATA_PORT_LBA2, 0); io_write(ATA_PORT_LBA2, 0);
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY); io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY);
SystemTimer::get().sleep_ms(1); SystemTimer::get().sleep_for_ms(1);
// No device on port // No device on port
if (io_read(ATA_PORT_STATUS) == 0) if (io_read(ATA_PORT_STATUS) == 0)
@@ -112,7 +112,7 @@ namespace Kernel
} }
io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET); io_write(ATA_PORT_COMMAND, ATA_COMMAND_IDENTIFY_PACKET);
SystemTimer::get().sleep_ms(1); SystemTimer::get().sleep_for_ms(1);
} }
TRY(wait(true)); TRY(wait(true));

View File

@@ -863,11 +863,21 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> Thread::sleep_or_eintr_ns(uint64_t ns) BAN::ErrorOr<void> Thread::sleep_or_eintr_for_ns(uint64_t timeout_ns)
{ {
if (is_interrupted_by_signal(true)) if (is_interrupted_by_signal(true))
return BAN::Error::from_errno(EINTR); 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<void> 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)) if (is_interrupted_by_signal(true))
return BAN::Error::from_errno(EINTR); return BAN::Error::from_errno(EINTR);
return {}; return {};

View File

@@ -229,11 +229,18 @@ namespace Kernel
return m_timer->pre_scheduler_sleep_ns(ns); 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; 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 timespec SystemTimer::real_time() const