Skip to content

Commit 9329867

Browse files
committed
Restore SMP peripheral polling cadence
This moves peripheral polling into the coroutine loop, so SMP runs keep same cadence as the single-core path, preventing delayed device IRQs. It also clears the published coroutine hart id when yielding to avoid exposing stale scheduler state to callers.
1 parent d06f1cb commit 9329867

File tree

2 files changed

+50
-68
lines changed

2 files changed

+50
-68
lines changed

coro.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,13 @@ static __thread coro_t *tls_running_coro = NULL;
234234
static coro_t *tls_running_coro = NULL;
235235
#endif
236236

237+
static inline void coro_clear_running_state(void)
238+
{
239+
coro_state.current_hart = CORO_HART_ID_IDLE;
240+
coro_state.running = NULL;
241+
tls_running_coro = NULL;
242+
}
243+
237244
/* Forward declarations */
238245

239246
#ifdef CORO_USE_ASM
@@ -287,9 +294,7 @@ static void jump_into(coro_t *co)
287294
static void jump_out(coro_t *co)
288295
{
289296
coro_context_t *context = co->context;
290-
coro_state.running = NULL;
291-
tls_running_coro = NULL;
292-
coro_state.current_hart = CORO_HART_ID_IDLE;
297+
coro_clear_running_state();
293298
_coro_switch(&context->ctx, &context->back_ctx);
294299
}
295300

@@ -350,9 +355,7 @@ static void jump_into(coro_t *co)
350355
static void jump_out(coro_t *co)
351356
{
352357
coro_context_t *context = co->context;
353-
coro_state.running = NULL;
354-
tls_running_coro = NULL;
355-
coro_state.current_hart = CORO_HART_ID_IDLE;
358+
coro_clear_running_state();
356359
swapcontext(&context->ctx, &context->back_ctx);
357360
}
358361

main.c

Lines changed: 41 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,40 @@ static void emu_update_vfs_interrupts(vm_t *vm)
141141
}
142142
#endif
143143

144+
static inline void emu_tick_peripherals(emu_state_t *emu)
145+
{
146+
vm_t *vm = &emu->vm;
147+
148+
if (emu->peripheral_update_ctr-- == 0) {
149+
emu->peripheral_update_ctr = 64;
150+
151+
u8250_check_ready(&emu->uart);
152+
if (emu->uart.in_ready)
153+
emu_update_uart_interrupts(vm);
154+
155+
#if SEMU_HAS(VIRTIONET)
156+
virtio_net_refresh_queue(&emu->vnet);
157+
if (emu->vnet.InterruptStatus)
158+
emu_update_vnet_interrupts(vm);
159+
#endif
160+
161+
#if SEMU_HAS(VIRTIOBLK)
162+
if (emu->vblk.InterruptStatus)
163+
emu_update_vblk_interrupts(vm);
164+
#endif
165+
166+
#if SEMU_HAS(VIRTIOSND)
167+
if (emu->vsnd.InterruptStatus)
168+
emu_update_vsnd_interrupts(vm);
169+
#endif
170+
171+
#if SEMU_HAS(VIRTIOFS)
172+
if (emu->vfs.InterruptStatus)
173+
emu_update_vfs_interrupts(vm);
174+
#endif
175+
}
176+
}
177+
144178
static void mem_load(hart_t *hart,
145179
uint32_t addr,
146180
uint8_t width,
@@ -796,13 +830,19 @@ static void hart_exec_loop(void *arg)
796830
while (!emu->stopped) {
797831
/* Check if hart is ready to execute (HSM state) */
798832
if (hart->hsm_status != SBI_HSM_STATE_STARTED) {
833+
emu_tick_peripherals(emu);
834+
emu_update_timer_interrupt(hart);
835+
emu_update_swi_interrupt(hart);
799836
/* Hart not started yet, yield and wait */
800837
coro_yield();
801838
continue;
802839
}
803840

804841
/* Execute a batch of instructions before yielding */
805842
for (int i = 0; i < 64; i++) {
843+
emu_tick_peripherals(emu);
844+
emu_update_timer_interrupt(hart);
845+
emu_update_swi_interrupt(hart);
806846
/* Execute one instruction */
807847
vm_step(hart);
808848

@@ -842,34 +882,7 @@ static int semu_step(emu_state_t *emu)
842882
* RFENCE extension is completely implemented.
843883
*/
844884
for (uint32_t i = 0; i < vm->n_hart; i++) {
845-
if (emu->peripheral_update_ctr-- == 0) {
846-
emu->peripheral_update_ctr = 64;
847-
848-
u8250_check_ready(&emu->uart);
849-
if (emu->uart.in_ready)
850-
emu_update_uart_interrupts(vm);
851-
852-
#if SEMU_HAS(VIRTIONET)
853-
virtio_net_refresh_queue(&emu->vnet);
854-
if (emu->vnet.InterruptStatus)
855-
emu_update_vnet_interrupts(vm);
856-
#endif
857-
858-
#if SEMU_HAS(VIRTIOBLK)
859-
if (emu->vblk.InterruptStatus)
860-
emu_update_vblk_interrupts(vm);
861-
#endif
862-
863-
#if SEMU_HAS(VIRTIOSND)
864-
if (emu->vsnd.InterruptStatus)
865-
emu_update_vsnd_interrupts(vm);
866-
#endif
867-
868-
#if SEMU_HAS(VIRTIOFS)
869-
if (emu->vfs.InterruptStatus)
870-
emu_update_vfs_interrupts(vm);
871-
#endif
872-
}
885+
emu_tick_peripherals(emu);
873886

874887
emu_update_timer_interrupt(vm->hart[i]);
875888
emu_update_swi_interrupt(vm->hart[i]);
@@ -993,41 +1006,7 @@ static int semu_run(emu_state_t *emu)
9931006
}
9941007
#endif
9951008

996-
/* Update peripherals periodically */
9971009
while (!emu->stopped) {
998-
/* Update peripherals every 64 instructions */
999-
if (emu->peripheral_update_ctr-- == 0) {
1000-
emu->peripheral_update_ctr = 64;
1001-
1002-
u8250_check_ready(&emu->uart);
1003-
if (emu->uart.in_ready)
1004-
emu_update_uart_interrupts(vm);
1005-
1006-
#if SEMU_HAS(VIRTIONET)
1007-
virtio_net_refresh_queue(&emu->vnet);
1008-
if (emu->vnet.InterruptStatus)
1009-
emu_update_vnet_interrupts(vm);
1010-
#endif
1011-
#if SEMU_HAS(VIRTIOBLK)
1012-
if (emu->vblk.InterruptStatus)
1013-
emu_update_vblk_interrupts(vm);
1014-
#endif
1015-
#if SEMU_HAS(VIRTIOSND)
1016-
if (emu->vsnd.InterruptStatus)
1017-
emu_update_vsnd_interrupts(vm);
1018-
#endif
1019-
#if SEMU_HAS(VIRTIOFS)
1020-
if (emu->vfs.InterruptStatus)
1021-
emu_update_vfs_interrupts(vm);
1022-
#endif
1023-
}
1024-
1025-
/* Update timer and software interrupts for all harts */
1026-
for (uint32_t i = 0; i < vm->n_hart; i++) {
1027-
emu_update_timer_interrupt(vm->hart[i]);
1028-
emu_update_swi_interrupt(vm->hart[i]);
1029-
}
1030-
10311010
/* Resume each hart's coroutine in round-robin fashion */
10321011
for (uint32_t i = 0; i < vm->n_hart; i++) {
10331012
coro_resume_hart(i);

0 commit comments

Comments
 (0)