Skip to content

Conversation

@spholz
Copy link
Member

@spholz spholz commented Dec 2, 2025

In the old idle loop implementation, lost wakeups can happen when the processor receives an interrupt immediately before wait_for_interrupt(). In that situation, we still go to sleep, even if the interrupt caused a thread to be runnable or we got notified of a runnable thread.

This new idle loop implementation instead runs with interrupts disabled. The only place in this new idle loop where we can get interrupts is during Processor::idle(). After that, we will only go to sleep if there are still no runnable threads.

With this new idle loop, boot time is reduced from 4 seconds down to 3 seconds on my x86-64 system when running in KVM. If I remove this busy wait, boot time is reduced down to 2 seconds (#26444):

@github-actions github-actions bot added the 👀 pr-needs-review PR needs review from a maintainer or community member label Dec 2, 2025
@spholz
Copy link
Member Author

spholz commented Dec 2, 2025

Before vs. after trace generated with the QEMU uftrace plugin and displayed in the Spall profiler:

(The trace snippets don't show the same NVMe interrupt and the first one is from a debug build, but that doesn't matter)

image image

In the new trace, we immediately schedule again after reading the data from disk. Before, we only caused a context switch after receiving a timer interrupt.

Copy link
Member

@LucasChollet LucasChollet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice improvement!

In the old idle loop implementation, lost wakeups can happen when the
processor receives an interrupt immediately before wait_for_interrupt().
In that situation, we still go to sleep, even if the interrupt caused
a thread to be runnable or we got notified of a runnable thread.

This new idle loop implementation instead runs with interrupts disabled.
The only place in this new idle loop where we can get interrupts is
during Processor::idle(). After that, we will only go to sleep if there
are still no runnable threads.
@spholz spholz force-pushed the kernel-fix-idle-loop branch from 6040fdb to 63ac033 Compare December 3, 2025 08:22
@spholz spholz merged commit 6bcd011 into SerenityOS:master Dec 3, 2025
19 of 20 checks passed
@spholz spholz deleted the kernel-fix-idle-loop branch December 3, 2025 13:04
@github-actions github-actions bot removed the 👀 pr-needs-review PR needs review from a maintainer or community member label Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants