Skip to content

Commit 2141656

Browse files
committed
hook write
1 parent 095427b commit 2141656

2 files changed

Lines changed: 34 additions & 5 deletions

File tree

core/src/syscall/unix/write.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,38 @@ trait WriteSyscall {
1111
) -> ssize_t;
1212
}
1313

14-
impl_syscall!(WriteSyscallFacade, IoUringWriteSyscall, NioWriteSyscall, RawWriteSyscall,
15-
write(fd: c_int, buf: *const c_void, len: size_t) -> ssize_t
16-
);
14+
//在最顶层对stdout/stderr/重入写入做早期旁路:直接调用原始系统调用,
15+
//跳过整个facade链(WriteSyscallFacade/IoUring/NIO),最小化每次info!()
16+
//调用write()时的函数调用开销。在QEMU等慢速平台上,每个额外的函数调用
17+
//可能耗时0.5-1ms,累积的开销会导致协程在10ms抢占窗口内无法完成工作。
18+
// Early bypass at the top-level dispatcher for stdout/stderr/re-entrant writes:
19+
// call the raw syscall directly, skipping the entire facade chain
20+
// (WriteSyscallFacade/IoUring/NIO). This minimizes function call overhead
21+
// per info!() → write() invocation. On slow platforms (QEMU), each extra
22+
// function call can cost 0.5-1ms, and cumulative overhead prevents coroutines
23+
// from completing work within the 10ms preemption window.
24+
#[must_use]
25+
pub extern "C" fn write(
26+
fn_ptr: Option<&extern "C" fn(c_int, *const c_void, size_t) -> ssize_t>,
27+
fd: c_int,
28+
buf: *const c_void,
29+
len: size_t,
30+
) -> ssize_t {
31+
cfg_if::cfg_if! {
32+
if #[cfg(all(target_os = "linux", feature = "io_uring"))] {
33+
static CHAIN: once_cell::sync::Lazy<
34+
WriteSyscallFacade<IoUringWriteSyscall<NioWriteSyscall<RawWriteSyscall>>>
35+
> = once_cell::sync::Lazy::new(Default::default);
36+
} else {
37+
static CHAIN: once_cell::sync::Lazy<WriteSyscallFacade<NioWriteSyscall<RawWriteSyscall>>> =
38+
once_cell::sync::Lazy::new(Default::default);
39+
}
40+
}
41+
if fd == libc::STDOUT_FILENO || fd == libc::STDERR_FILENO {
42+
return RawWriteSyscall::default().write(fn_ptr, fd, buf, len);
43+
}
44+
CHAIN.write(fn_ptr, fd, buf, len)
45+
}
1746

1847
impl_facade!(WriteSyscallFacade, WriteSyscall,
1948
write(fd: c_int, buf: *const c_void, len: size_t) -> ssize_t

hook/src/syscall/unix.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ impl_hook!(PREADV, preadv(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: o
6262
impl_hook!(RECVMSG, recvmsg(fd: c_int, msg: *mut msghdr, flags: c_int) -> ssize_t);
6363
impl_hook!(SEND, send(fd: c_int, buf: *const c_void, len: size_t, flags: c_int) -> ssize_t);
6464
impl_hook!(SENDTO, sendto(fd: c_int, buf: *const c_void, len: size_t, flags: c_int, addr: *const sockaddr, addrlen: socklen_t) -> ssize_t);
65+
impl_hook!(WRITE, write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t);
6566
impl_hook!(PWRITE, pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_t) -> ssize_t);
6667
impl_hook!(WRITEV, writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t);
6768
impl_hook!(PWRITEV, pwritev(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off_t) -> ssize_t);
@@ -82,7 +83,6 @@ impl_hook!(RENAMEAT2, renameat2(olddirfd: c_int, oldpath: *const c_char, newdirf
8283
// NOTE: unhook poll due to mio's poller
8384
// impl_hook!(POLL, poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int);
8485

85-
// NOTE: unhook write/pthread_mutex_lock/pthread_mutex_unlock due to stack overflow or bug
86-
// impl_hook!(WRITE, write(fd: c_int, buf: *const c_void, count: size_t) -> ssize_t);
86+
// NOTE: unhook pthread_mutex_lock/pthread_mutex_unlock due to stack overflow or bug
8787
// impl_hook!(PTHREAD_MUTEX_LOCK, pthread_mutex_lock(lock: *mut pthread_mutex_t) -> c_int);
8888
// impl_hook!(PTHREAD_MUTEX_UNLOCK, pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> c_int);

0 commit comments

Comments
 (0)