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
// 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_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> 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));
return sleep_or_eintr_ns(ms * 1'000'000);
ASSERT(!BAN::Math::will_multiplication_overflow<uint64_t>(timeout_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)
{

View File

@@ -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<uint64_t>(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<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; }

View File

@@ -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))

View File

@@ -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<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()
: 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)

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
// 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 {};
}

View File

@@ -50,6 +50,7 @@ namespace Kernel
[](void* _devfs)
{
auto* devfs = static_cast<DevFileSystem*>(_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
));

View File

@@ -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);

View File

@@ -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)

View File

@@ -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));

View File

@@ -863,11 +863,21 @@ namespace Kernel
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))
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))
return BAN::Error::from_errno(EINTR);
return {};

View File

@@ -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