Skip to content

Commit ceb9196

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 0c0ec1e commit ceb9196

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
@@ -1145,9 +1145,6 @@ static int semu_run(emu_state_t *emu)
11451145
pfd_count++;
11461146
}
11471147
#endif
1148-
#ifdef __APPLE__
1149-
(void) timer_index;
1150-
#endif
11511148

11521149
/* Add UART input fd (stdin for keyboard input) */
11531150
if (emu->uart.in_fd >= 0 && pfd_count < poll_capacity) {
@@ -1182,16 +1179,24 @@ static int semu_run(emu_state_t *emu)
11821179
if (pfd_count > 0) {
11831180
int nevents = poll(pfds, pfd_count, poll_timeout);
11841181
if (nevents > 0) {
1185-
#ifndef __APPLE__
1186-
/* Consume timer expiration event on Linux (timerfd) */
1182+
/* Consume timer expiration events to prevent fd staying
1183+
* readable
1184+
*/
11871185
if (timer_index >= 0 &&
11881186
(pfds[timer_index].revents & POLLIN)) {
1187+
#ifdef __APPLE__
1188+
/* drain kqueue events with non-blocking kevent */
1189+
struct kevent events[32];
1190+
struct timespec timeout_zero = {0, 0};
1191+
kevent(kq, NULL, 0, events, 32, &timeout_zero);
1192+
#else
1193+
/* Linux: read timerfd to consume expiration count */
11891194
uint64_t expirations;
11901195
ssize_t ret_read = read(wfi_timer_fd, &expirations,
11911196
sizeof(expirations));
11921197
(void) ret_read;
1193-
}
11941198
#endif
1199+
}
11951200
} else if (nevents < 0 && errno != EINTR) {
11961201
perror("poll");
11971202
}

0 commit comments

Comments
 (0)