Skip to content

Commit d8b31e0

Browse files
committed
Drain kqueue events to prevent WFI busy-loop
The poll()-based event loop was not consuming kqueue events on macOS, causing the kqueue fd to remain readable after the first timer tick. This defeated the WFI sleep optimization by making poll(..., -1) return immediately instead of blocking when all harts are idle. Root cause: - Linux path: timerfd is consumed via read() after poll() - macOS path: kqueue events were never drained after poll() - Result: kqueue fd stays readable → poll() never blocks → 100% CPU
1 parent c6a1d5f commit d8b31e0

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

main.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,9 +1170,6 @@ static int semu_run(emu_state_t *emu)
11701170
pfd_count++;
11711171
}
11721172
#endif
1173-
#ifdef __APPLE__
1174-
(void) timer_index;
1175-
#endif
11761173

11771174
/* Add UART input fd (stdin for keyboard input) */
11781175
if (emu->uart.in_fd >= 0 && pfd_count < poll_capacity) {
@@ -1207,16 +1204,24 @@ static int semu_run(emu_state_t *emu)
12071204
if (pfd_count > 0) {
12081205
int nevents = poll(pfds, pfd_count, poll_timeout);
12091206
if (nevents > 0) {
1210-
#ifndef __APPLE__
1211-
/* Consume timer expiration event on Linux (timerfd) */
1207+
/* Consume timer expiration events to prevent fd staying
1208+
* readable
1209+
*/
12121210
if (timer_index >= 0 &&
12131211
(pfds[timer_index].revents & POLLIN)) {
1212+
#ifdef __APPLE__
1213+
/* drain kqueue events with non-blocking kevent */
1214+
struct kevent events[32];
1215+
struct timespec timeout_zero = {0, 0};
1216+
kevent(kq, NULL, 0, events, 32, &timeout_zero);
1217+
#else
1218+
/* Linux: read timerfd to consume expiration count */
12141219
uint64_t expirations;
12151220
ssize_t ret_read = read(wfi_timer_fd, &expirations,
12161221
sizeof(expirations));
12171222
(void) ret_read;
1218-
}
12191223
#endif
1224+
}
12201225
} else if (nevents < 0 && errno != EINTR) {
12211226
perror("poll");
12221227
}

0 commit comments

Comments
 (0)