Skip to content

Commit c02a012

Browse files
committed
Implement clock_nanosleep and make epoll_wait complete nearly instantly
1 parent b5e7a27 commit c02a012

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

lib/tinykvm/linux/system_calls.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,30 @@ void Machine::setup_linux_system_calls()
10131013
SYSPRINT("clock_gettime(clk=%lld, buf=0x%llX) = %lld\n",
10141014
regs.rdi, regs.rsi, regs.rax);
10151015
cpu.set_registers(regs);
1016+
//cpu.machine().threads().suspend_and_yield();
1017+
});
1018+
Machine::install_syscall_handler(
1019+
SYS_clock_nanosleep, [](vCPU& cpu) { // clock_nanosleep
1020+
auto& regs = cpu.registers();
1021+
// We don't allow sleeping in the guest
1022+
// but we can set the remaining time to the requested value
1023+
const uint64_t g_buf = regs.rdx;
1024+
const uint64_t g_rem = regs.r10;
1025+
struct timespec ts;
1026+
struct timespec ts_rem {};
1027+
cpu.machine().copy_from_guest(&ts, g_buf, sizeof(ts));
1028+
const int result =
1029+
clock_nanosleep(CLOCK_MONOTONIC, regs.rsi, &ts, &ts_rem);
1030+
if (result < 0) {
1031+
regs.rax = -errno;
1032+
} else {
1033+
if (g_rem != 0x0)
1034+
cpu.machine().copy_to_guest(g_rem, &ts_rem, sizeof(ts_rem));
1035+
regs.rax = 0;
1036+
}
1037+
SYSPRINT("clock_nanosleep(clk=%lld, flags=%lld, req=0x%llX, rem=%lld) = %lld\n",
1038+
regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.rax);
1039+
cpu.set_registers(regs);
10161040
});
10171041
Machine::install_syscall_handler(
10181042
SYS_exit_group, [](vCPU& cpu)
@@ -1218,9 +1242,14 @@ void Machine::setup_linux_system_calls()
12181242
return;
12191243
}
12201244
std::array<struct epoll_event, 1024> guest_events;
1245+
// Only wait for 150ns, as we are *not* pre-empting the guest
1246+
const struct timespec ts {
1247+
.tv_sec = 0,
1248+
.tv_nsec = 150,
1249+
};
12211250
const int epollfd = cpu.machine().fds().translate(vfd);
12221251
const int result =
1223-
epoll_wait(epollfd, guest_events.data(), maxevents, timeout);
1252+
epoll_pwait2(epollfd, guest_events.data(), maxevents, &ts, nullptr);
12241253
// Copy events back to guest
12251254
if (result > 0)
12261255
{
@@ -1238,7 +1267,8 @@ void Machine::setup_linux_system_calls()
12381267
// XXX: This is a giga hack.
12391268
cpu.machine().threads().suspend_and_yield();
12401269
}
1241-
SYSPRINT("epoll_wait(...) = %lld\n", regs.rax);
1270+
SYSPRINT("epoll_wait(fd=%d (%lld), g_events=0x%lX, maxevents=%d, timeout=%d) = %lld\n",
1271+
vfd, regs.rdi, g_events, maxevents, timeout, regs.rax);
12421272
cpu.set_registers(regs);
12431273
});
12441274
Machine::install_syscall_handler(

0 commit comments

Comments
 (0)