Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 13 additions & 15 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1191,22 +1191,20 @@ static int semu_run(emu_state_t *emu)
size_t pfd_count = 0;
int timer_index = -1;

/* Add periodic timer fd (1ms interval for guest timer emulation).
* Only add timer when ALL harts are active (none idle) to allow
* poll() to sleep when any harts are in WFI. When harts are idle,
* timer updates can be deferred until they wake up.
*
* During SMP boot (started_harts < vm->n_hart), always include the
* timer to ensure secondary harts can complete initialization. Only
* apply conditional exclusion after all harts have started.
*
* For single-hart configurations (n_hart == 1), disable
* optimization entirely to avoid boot issues, as the first hart
* starts immediately.
/* Add periodic timer fd (1ms interval). Excluded when harts are
* idle to allow poll() sleep, but always included during:
* 1. Single-hart mode (n_hart == 1)
* 2. Boot phase (!boot_complete) - prevents deadlock when kernel
* briefly puts all harts in WFI while waiting for timer IRQ
* 3. Active execution (idle_harts == 0)
*/
bool all_harts_started = (started_harts >= vm->n_hart);
const uint64_t BOOT_SETTLE_ITERATIONS = 5000;
bool boot_complete =
all_harts_started &&
(emu->peripheral_update_ctr > BOOT_SETTLE_ITERATIONS);
Copy link

@cubic-dev-ai cubic-dev-ai bot Nov 2, 2025

Choose a reason for hiding this comment

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

peripheral_update_ctr never exceeds 64 because it is a countdown reset to 64 each tick, so this > BOOT_SETTLE_ITERATIONS check never succeeds and boot_complete stays false. That keeps the timer and UART fds permanently active, undoing the post-boot idle optimization this block is supposed to preserve.

Prompt for AI agents
Address the following comment on main.c at line 1217:

<comment>`peripheral_update_ctr` never exceeds 64 because it is a countdown reset to 64 each tick, so this `&gt; BOOT_SETTLE_ITERATIONS` check never succeeds and `boot_complete` stays false. That keeps the timer and UART fds permanently active, undoing the post-boot idle optimization this block is supposed to preserve.</comment>

<file context>
@@ -1203,10 +1203,20 @@ static int semu_run(emu_state_t *emu)
+            const uint64_t BOOT_SETTLE_ITERATIONS = 5000;
+            bool boot_complete =
+                all_harts_started &amp;&amp;
+                (emu-&gt;peripheral_update_ctr &gt; BOOT_SETTLE_ITERATIONS);
+            bool harts_active = (vm-&gt;n_hart == 1) || !boot_complete ||
+                                (idle_harts == 0);
</file context>
Fix with Cubic

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

peripheral_update_ctr is a countdown timer (64→0→64) and will never exceed 5000, meaning boot_complete stays false permanently. This breaks the intended idle optimization.

bool harts_active =
(vm->n_hart == 1) || !all_harts_started || (idle_harts == 0);
(vm->n_hart == 1) || !boot_complete || (idle_harts == 0);
#ifdef __APPLE__
/* macOS: use kqueue with EVFILT_TIMER */
if (kq >= 0 && pfd_count < poll_capacity && harts_active) {
Expand All @@ -1227,7 +1225,7 @@ static int semu_run(emu_state_t *emu)
/* Add UART input fd (stdin for keyboard input).
* Only add UART when:
* 1. Single-hart configuration (n_hart == 1), OR
* 2. Not all harts started (!all_harts_started), OR
* 2. Boot not complete (!boot_complete), OR
* 3. All harts are active (idle_harts == 0), OR
* 4. A hart is actively waiting for UART input
*
Expand All @@ -1236,7 +1234,7 @@ static int semu_run(emu_state_t *emu)
* input (Ctrl+A x) may be delayed by up to poll_timeout (10ms)
* when harts are idle, which is acceptable for an emulator.
*/
bool need_uart = (vm->n_hart == 1) || !all_harts_started ||
bool need_uart = (vm->n_hart == 1) || !boot_complete ||
(idle_harts == 0) || emu->uart.has_waiting_hart;
if (emu->uart.in_fd >= 0 && pfd_count < poll_capacity &&
need_uart) {
Expand Down
Loading