diff --git a/core/docs/en/coroutine.md b/core/docs/en/coroutine.md index 9029209b..80f5fbdd 100644 --- a/core/docs/en/coroutine.md +++ b/core/docs/en/coroutine.md @@ -6,6 +6,38 @@ author: loongs-zhang # Coroutine Overview +## Usage + +```rust +use open_coroutine_core::common::constants::CoroutineState; +use open_coroutine_core::coroutine::Coroutine; + +fn main() -> std::io::Result<()> { + let mut co = Coroutine::new( + // optional coroutine name + None, + |suspender, input| { + assert_eq!(1, input); + assert_eq!(3, suspender.suspend_with(2)); + 4 + }, + // optional stack size + None, + // optional coroutine priority + None, + )?; + // Macro `co!` is equivalent to the code above + // let mut co = open_coroutine_core::co!(|suspender, input| { + // assert_eq!(1, input); + // assert_eq!(3, suspender.suspend_with(2)); + // 4 + // })?; + assert_eq!(CoroutineState::Suspend(2, 0), co.resume_with(1)?); + assert_eq!(CoroutineState::Complete(4), co.resume_with(3)?); + Ok(()) +} +``` + ## What is coroutine? A [coroutine](https://en.wikipedia.org/wiki/Coroutine) is a function that can be paused and resumed, yielding values to @@ -15,6 +47,26 @@ resumed. The above is excerpted from [corosensei](https://github.com/Amanieu/corosensei). +## Coroutine VS Thread + +| | coroutine | thread | +|-------------------|-----------|---------| +| switch efficiency | ✅ Higher | ❌ High | +| memory efficiency | KB/MB | KB/MB | +| scheduled by OS | ❌ | ✅ | +| stack grow | ✅ | ❌ | + +## Stackfull VS Stackless + +| | stackfull | stackless | +|-------------------|-----------|-----------| +| switch efficiency | ❌ High | ✅ Higher | +| memory efficiency | ❌ KB/MB | ✅ Bytes | +| limitations | ✅ Few | ❌ Many | + +In general, if the requirements for resource utilization and switching performance are not very strict, using a +stackfull approach would be more convenient and the code would be easier to maintain. + ## State in open-coroutine ```text diff --git a/core/docs/en/monitor.md b/core/docs/en/monitor.md index cb459139..07649af3 100644 --- a/core/docs/en/monitor.md +++ b/core/docs/en/monitor.md @@ -21,6 +21,37 @@ The `preemptive` feature currently supports the following targets: ✅ Tested and stable; ⚠️ Tested but unstable; ❌ Not supported. +## Usage + +```rust +use open_coroutine_core::co; +use open_coroutine_core::common::constants::CoroutineState; +use open_coroutine_core::coroutine::Coroutine; + +fn main() -> std::io::Result<()> { + // Simulate the most extreme dead loop, if the preemptive feature + // is not enabled, it will remain stuck in a dead loop after resume. + let mut coroutine: Coroutine<(), (), ()> = co!(|_, ()| { loop {} })?; + assert_eq!(CoroutineState::Suspend((), 0), coroutine.resume()?); + assert_eq!(CoroutineState::Suspend((), 0), coroutine.state()); + Ok(()) +} +``` + +## What is monitor? + +The `monitor` mod implements the `preemptive` feature for open-coroutine, which allows the coroutine to be preempted +when it is running for a long time. + +## Why preempt + +After a `Coroutine::resume_with`, a coroutine may occupy the scheduling thread for a long time, thereby slowing down +other coroutines scheduled by that scheduling thread. To solve this problem, we introduce preemptive scheduling, which +automatically suspends coroutines that are stuck in long-term execution and allows other coroutines to execute. + +The coroutine occupies scheduling threads for a long time in two scenarios: getting stuck in heavy computing or syscall. +The following only solves the problem of getting stuck in heavy computing. + ## How it works ```mermaid diff --git a/core/src/coroutine/korosensei.rs b/core/src/coroutine/korosensei.rs index adcfa51a..66c9cdbe 100644 --- a/core/src/coroutine/korosensei.rs +++ b/core/src/coroutine/korosensei.rs @@ -381,20 +381,23 @@ where ///# Errors /// if stack allocate failed. pub fn new( - name: String, + name: Option, f: F, - stack_size: usize, + stack_size: Option, priority: Option, ) -> std::io::Result where F: FnOnce(&Suspender, Param) -> Return + 'static, { - let stack_size = stack_size.max(crate::common::page_size()); + let stack_size = stack_size + .unwrap_or(crate::common::constants::DEFAULT_STACK_SIZE) + .max(crate::common::page_size()); let stack = DefaultStack::new(stack_size)?; let stack_infos = UnsafeCell::new(VecDeque::from([StackInfo { stack_top: stack.base().get(), stack_bottom: stack.limit().get(), }])); + let name = name.unwrap_or_else(|| uuid::Uuid::new_v4().to_string()); let co_name = name.clone().leak(); let inner = corosensei::Coroutine::with_stack(stack, move |y, p| { catch!( diff --git a/core/src/coroutine/mod.rs b/core/src/coroutine/mod.rs index 0403fd9f..8e577615 100644 --- a/core/src/coroutine/mod.rs +++ b/core/src/coroutine/mod.rs @@ -29,34 +29,19 @@ macro_rules! co { $crate::coroutine::Coroutine::new($name, $f, $size, $priority) }; ($f:expr, $size:literal, $priority:literal $(,)?) => { - $crate::coroutine::Coroutine::new( - uuid::Uuid::new_v4().to_string(), - $f, - $size, - Some($priority), - ) + $crate::coroutine::Coroutine::new(None, $f, $size, Some($priority)) }; ($name:expr, $f:expr, $size:expr $(,)?) => { $crate::coroutine::Coroutine::new($name, $f, $size, None) }; ($f:expr, $size:literal $(,)?) => { - $crate::coroutine::Coroutine::new(uuid::Uuid::new_v4().to_string(), $f, $size, None) + $crate::coroutine::Coroutine::new(None, $f, $size, None) }; ($name:expr, $f:expr $(,)?) => { - $crate::coroutine::Coroutine::new( - $name, - $f, - $crate::common::constants::DEFAULT_STACK_SIZE, - None, - ) + $crate::coroutine::Coroutine::new($name, $f, None, None) }; ($f:expr $(,)?) => { - $crate::coroutine::Coroutine::new( - uuid::Uuid::new_v4().to_string(), - $f, - $crate::common::constants::DEFAULT_STACK_SIZE, - None, - ) + $crate::coroutine::Coroutine::new(None, $f, None, None) }; } diff --git a/core/src/net/event_loop.rs b/core/src/net/event_loop.rs index a4e926ae..4e61f3da 100644 --- a/core/src/net/event_loop.rs +++ b/core/src/net/event_loop.rs @@ -18,9 +18,9 @@ use std::time::Duration; cfg_if::cfg_if! { if #[cfg(all(target_os = "linux", feature = "io_uring"))] { - use libc::{epoll_event, iovec, msghdr, off_t, size_t, sockaddr, socklen_t}; use dashmap::DashMap; - use std::ffi::c_longlong; + use libc::{epoll_event, iovec, mode_t, msghdr, off_t, size_t, sockaddr, socklen_t}; + use std::ffi::{c_longlong, c_uint}; } } @@ -441,6 +441,10 @@ impl_io_uring!(pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_ impl_io_uring!(writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t); impl_io_uring!(pwritev(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off_t) -> ssize_t); impl_io_uring!(sendmsg(fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t); +impl_io_uring!(fsync(fd: c_int) -> c_int); +impl_io_uring!(mkdirat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int); +impl_io_uring!(renameat(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char) -> c_int); +impl_io_uring!(renameat2(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_uint) -> c_int); #[cfg(all(test, not(all(unix, feature = "preemptive"))))] mod tests { diff --git a/core/src/net/mod.rs b/core/src/net/mod.rs index fffe5fe8..bcb2bf37 100644 --- a/core/src/net/mod.rs +++ b/core/src/net/mod.rs @@ -13,8 +13,8 @@ use std::time::Duration; cfg_if::cfg_if! { if #[cfg(all(target_os = "linux", feature = "io_uring"))] { - use libc::{epoll_event, iovec, msghdr, off_t, size_t, sockaddr, socklen_t}; - use std::ffi::c_void; + use libc::{epoll_event, iovec, mode_t, msghdr, off_t, size_t, sockaddr, socklen_t}; + use std::ffi::{c_char, c_uint, c_void}; } } @@ -276,3 +276,7 @@ impl_io_uring!(pwrite(fd: c_int, buf: *const c_void, count: size_t, offset: off_ impl_io_uring!(writev(fd: c_int, iov: *const iovec, iovcnt: c_int) -> ssize_t); impl_io_uring!(pwritev(fd: c_int, iov: *const iovec, iovcnt: c_int, offset: off_t) -> ssize_t); impl_io_uring!(sendmsg(fd: c_int, msg: *const msghdr, flags: c_int) -> ssize_t); +impl_io_uring!(fsync(fd: c_int) -> c_int); +impl_io_uring!(mkdirat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int); +impl_io_uring!(renameat(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char) -> c_int); +impl_io_uring!(renameat2(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_uint) -> c_int); diff --git a/core/src/scheduler.rs b/core/src/scheduler.rs index 07f65cca..eb9067b9 100644 --- a/core/src/scheduler.rs +++ b/core/src/scheduler.rs @@ -177,9 +177,9 @@ impl<'s> Scheduler<'s> { priority: Option, ) -> std::io::Result<()> { self.submit_raw_co(co!( - format!("{}@{}", self.name(), uuid::Uuid::new_v4()), + Some(format!("{}@{}", self.name(), uuid::Uuid::new_v4())), f, - stack_size.unwrap_or(self.stack_size()), + Some(stack_size.unwrap_or(self.stack_size())), priority )?) } diff --git a/core/src/syscall/mod.rs b/core/src/syscall/mod.rs index 0e34350c..cc4f184e 100644 --- a/core/src/syscall/mod.rs +++ b/core/src/syscall/mod.rs @@ -1,5 +1,5 @@ macro_rules! syscall_mod { - ($($mod_name: ident);*) => { + ($($mod_name: ident);*$(;)?) => { $( pub use $mod_name::$mod_name; mod $mod_name; diff --git a/core/src/syscall/unix/fsync.rs b/core/src/syscall/unix/fsync.rs new file mode 100644 index 00000000..c8fec3ee --- /dev/null +++ b/core/src/syscall/unix/fsync.rs @@ -0,0 +1,32 @@ +use once_cell::sync::Lazy; +use std::ffi::c_int; + +#[must_use] +pub extern "C" fn fsync( + fn_ptr: Option<&extern "C" fn(c_int) -> c_int>, + fd: c_int, +) -> c_int { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", feature = "io_uring"))] { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + } else { + static CHAIN: Lazy> = Lazy::new(Default::default); + } + } + CHAIN.fsync(fn_ptr, fd) +} + +trait FsyncSyscall { + extern "C" fn fsync( + &self, + fn_ptr: Option<&extern "C" fn(c_int) -> c_int>, + fd: c_int, + ) -> c_int; +} + +impl_facade!(FsyncSyscallFacade, FsyncSyscall, fsync(fd: c_int) -> c_int); + +impl_io_uring!(IoUringFsyncSyscall, FsyncSyscall, fsync(fd: c_int) -> c_int); + +impl_raw!(RawFsyncSyscall, FsyncSyscall, fsync(fd: c_int) -> c_int); diff --git a/core/src/syscall/unix/mkdirat.rs b/core/src/syscall/unix/mkdirat.rs new file mode 100644 index 00000000..86aa47e8 --- /dev/null +++ b/core/src/syscall/unix/mkdirat.rs @@ -0,0 +1,43 @@ +use libc::mode_t; +use once_cell::sync::Lazy; +use std::ffi::{c_char, c_int}; + +#[must_use] +pub extern "C" fn mkdirat( + fn_ptr: Option<&extern "C" fn(c_int, *const c_char, mode_t) -> c_int>, + dirfd: c_int, + pathname: *const c_char, + mode: mode_t, +) -> c_int { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", feature = "io_uring"))] { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + } else { + static CHAIN: Lazy> = Lazy::new(Default::default); + } + } + CHAIN.mkdirat(fn_ptr, dirfd, pathname, mode) +} + +trait MkdiratSyscall { + extern "C" fn mkdirat( + &self, + fn_ptr: Option<&extern "C" fn(c_int, *const c_char, mode_t) -> c_int>, + dirfd: c_int, + pathname: *const c_char, + mode: mode_t, + ) -> c_int; +} + +impl_facade!(MkdiratSyscallFacade, MkdiratSyscall, + mkdirat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int +); + +impl_io_uring!(IoUringMkdiratSyscall, MkdiratSyscall, + mkdirat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int +); + +impl_raw!(RawMkdiratSyscall, MkdiratSyscall, + mkdirat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int +); diff --git a/core/src/syscall/unix/mod.rs b/core/src/syscall/unix/mod.rs index 9374369a..7e9da196 100644 --- a/core/src/syscall/unix/mod.rs +++ b/core/src/syscall/unix/mod.rs @@ -3,7 +3,10 @@ use once_cell::sync::Lazy; use std::ffi::c_int; macro_rules! impl_facade { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident($($arg: ident : $arg_type: ty),*$(,)?) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] struct $struct_name { @@ -40,7 +43,10 @@ macro_rules! impl_facade { } macro_rules! impl_io_uring { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident($($arg: ident : $arg_type: ty),*$(,)?) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] #[cfg(all(target_os = "linux", feature = "io_uring"))] @@ -111,7 +117,10 @@ macro_rules! impl_io_uring { } macro_rules! impl_io_uring_read { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*$(,)?) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] #[cfg(all(target_os = "linux", feature = "io_uring"))] @@ -194,7 +203,10 @@ macro_rules! impl_io_uring_read { } macro_rules! impl_io_uring_write { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*$(,)?) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] #[cfg(all(target_os = "linux", feature = "io_uring"))] @@ -277,7 +289,10 @@ macro_rules! impl_io_uring_write { } macro_rules! impl_nio_read { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident($fd: ident : $fd_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] struct $struct_name { @@ -332,8 +347,15 @@ macro_rules! impl_nio_read { } macro_rules! impl_nio_read_buf { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, - $buf: ident : $buf_type: ty, $len: ident : $len_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident( + $fd: ident : $fd_type: ty, + $buf: ident : $buf_type: ty, + $len: ident : $len_type: ty + $(, $($arg: ident : $arg_type: ty),*)? + ) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] struct $struct_name { @@ -343,11 +365,18 @@ macro_rules! impl_nio_read_buf { impl $trait_name for $struct_name { extern "C" fn $syscall( &self, - fn_ptr: Option<&extern "C" fn($fd_type, $buf_type, $len_type, $($arg_type),*) -> $result>, + fn_ptr: Option< + &extern "C" fn( + $fd_type, + $buf_type, + $len_type + $(, $($arg_type),*)? + ) -> $result + >, $fd: $fd_type, $buf: $buf_type, - $len: $len_type, - $($arg: $arg_type),* + $len: $len_type + $(, $($arg: $arg_type),*)? ) -> $result { let blocking = $crate::syscall::is_blocking($fd); if blocking { @@ -363,7 +392,7 @@ macro_rules! impl_nio_read_buf { $fd, ($buf as usize + received) as *mut std::ffi::c_void, $len - received, - $($arg, )* + $($($arg, )*)? ); if r != -1 { $crate::syscall::reset_errno(); @@ -402,8 +431,15 @@ macro_rules! impl_nio_read_buf { } macro_rules! impl_nio_read_iovec { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, - $iov: ident : $iov_type: ty, $iovcnt: ident : $iovcnt_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident( + $fd: ident : $fd_type: ty, + $iov: ident : $iov_type: ty, + $iovcnt: ident : $iovcnt_type: ty, + $($arg: ident : $arg_type: ty),* + ) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] struct $struct_name { @@ -413,7 +449,14 @@ macro_rules! impl_nio_read_iovec { impl $trait_name for $struct_name { extern "C" fn $syscall( &self, - fn_ptr: Option<&extern "C" fn($fd_type, $iov_type, $iovcnt_type, $($arg_type),*) -> $result>, + fn_ptr: Option< + &extern "C" fn( + $fd_type, + $iov_type, + $iovcnt_type, + $($arg_type),* + ) -> $result + >, $fd: $fd_type, $iov: $iov_type, $iovcnt: $iovcnt_type, @@ -521,8 +564,15 @@ macro_rules! impl_nio_read_iovec { } macro_rules! impl_nio_write_buf { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, - $buf: ident : $buf_type: ty, $len: ident : $len_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident( + $fd: ident : $fd_type: ty, + $buf: ident : $buf_type: ty, + $len: ident : $len_type: ty + $(, $($arg: ident : $arg_type: ty),*)? + ) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] struct $struct_name { @@ -532,11 +582,18 @@ macro_rules! impl_nio_write_buf { impl $trait_name for $struct_name { extern "C" fn $syscall( &self, - fn_ptr: Option<&extern "C" fn($fd_type, $buf_type, $len_type, $($arg_type),*) -> $result>, + fn_ptr: Option< + &extern "C" fn( + $fd_type, + $buf_type, + $len_type + $(, $($arg_type),*)? + ) -> $result + >, $fd: $fd_type, $buf: $buf_type, - $len: $len_type, - $($arg: $arg_type),* + $len: $len_type + $(, $($arg: $arg_type),*)? ) -> $result { let blocking = $crate::syscall::is_blocking($fd); if blocking { @@ -552,7 +609,7 @@ macro_rules! impl_nio_write_buf { $fd, ($buf as usize + sent) as *const std::ffi::c_void, $len - sent, - $($arg, )* + $($($arg, )*)? ); if r != -1 { $crate::syscall::reset_errno(); @@ -591,8 +648,15 @@ macro_rules! impl_nio_write_buf { } macro_rules! impl_nio_write_iovec { - ( $struct_name:ident, $trait_name: ident, $syscall: ident($fd: ident : $fd_type: ty, - $iov: ident : $iov_type: ty, $iovcnt: ident : $iovcnt_type: ty, $($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name:ident, $trait_name: ident, + $syscall: ident( + $fd: ident : $fd_type: ty, + $iov: ident : $iov_type: ty, + $iovcnt: ident : $iovcnt_type: ty, + $($arg: ident : $arg_type: ty),* + ) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Default)] struct $struct_name { @@ -602,7 +666,14 @@ macro_rules! impl_nio_write_iovec { impl $trait_name for $struct_name { extern "C" fn $syscall( &self, - fn_ptr: Option<&extern "C" fn($fd_type, $iov_type, $iovcnt_type, $($arg_type),*) -> $result>, + fn_ptr: Option< + &extern "C" fn( + $fd_type, + $iov_type, + $iovcnt_type, + $($arg_type),* + ) -> $result + >, $fd: $fd_type, $iov: $iov_type, $iovcnt: $iovcnt_type, @@ -703,7 +774,10 @@ macro_rules! impl_nio_write_iovec { } macro_rules! impl_raw { - ( $struct_name: ident, $trait_name: ident, $syscall: ident($($arg: ident : $arg_type: ty),*) -> $result: ty ) => { + ( + $struct_name: ident, $trait_name: ident, + $syscall: ident($($arg: ident : $arg_type: ty),*$(,)?) -> $result: ty + ) => { #[repr(C)] #[derive(Debug, Copy, Clone, Default)] struct $struct_name {} @@ -725,7 +799,10 @@ macro_rules! impl_raw { } #[cfg(target_os = "linux")] -syscall_mod!(accept4); +syscall_mod!( + accept4; + renameat2; +); syscall_mod!( accept; close; @@ -758,10 +835,13 @@ syscall_mod!( write; writev; mkdir; + mkdirat; + fsync; rmdir; + renameat; lseek; link; - unlink + unlink; ); static SEND_TIME_LIMIT: Lazy> = Lazy::new(Default::default); diff --git a/core/src/syscall/unix/read.rs b/core/src/syscall/unix/read.rs index 17975783..364c5372 100644 --- a/core/src/syscall/unix/read.rs +++ b/core/src/syscall/unix/read.rs @@ -41,7 +41,7 @@ impl_io_uring_read!(IoUringReadSyscall, ReadSyscall, ); impl_nio_read_buf!(NioReadSyscall, ReadSyscall, - read(fd: c_int, buf: *mut c_void, len: size_t, ) -> ssize_t + read(fd: c_int, buf: *mut c_void, len: size_t) -> ssize_t ); impl_raw!(RawReadSyscall, ReadSyscall, diff --git a/core/src/syscall/unix/renameat.rs b/core/src/syscall/unix/renameat.rs new file mode 100644 index 00000000..01c4ea76 --- /dev/null +++ b/core/src/syscall/unix/renameat.rs @@ -0,0 +1,44 @@ +use once_cell::sync::Lazy; +use std::ffi::{c_char, c_int}; + +#[must_use] +pub extern "C" fn renameat( + fn_ptr: Option<&extern "C" fn(c_int, *const c_char, c_int, *const c_char) -> c_int>, + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, +) -> c_int { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", feature = "io_uring"))] { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + } else { + static CHAIN: Lazy> = Lazy::new(Default::default); + } + } + CHAIN.renameat(fn_ptr, olddirfd, oldpath, newdirfd, newpath) +} + +trait RenameatSyscall { + extern "C" fn renameat( + &self, + fn_ptr: Option<&extern "C" fn(c_int, *const c_char, c_int, *const c_char) -> c_int>, + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, + ) -> c_int; +} + +impl_facade!(RenameatSyscallFacade, RenameatSyscall, + renameat(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char) -> c_int +); + +impl_io_uring!(IoUringRenameatSyscall, RenameatSyscall, + renameat(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char) -> c_int +); + +impl_raw!(RawRenameatSyscall, RenameatSyscall, + renameat(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char) -> c_int +); diff --git a/core/src/syscall/unix/renameat2.rs b/core/src/syscall/unix/renameat2.rs new file mode 100644 index 00000000..e6083b9d --- /dev/null +++ b/core/src/syscall/unix/renameat2.rs @@ -0,0 +1,64 @@ +use once_cell::sync::Lazy; +use std::ffi::{c_char, c_int, c_uint}; + +#[must_use] +pub extern "C" fn renameat2( + fn_ptr: Option<&extern "C" fn(c_int, *const c_char, c_int, *const c_char, c_uint) -> c_int>, + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, + flags: c_uint, +) -> c_int { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", feature = "io_uring"))] { + static CHAIN: Lazy>> = + Lazy::new(Default::default); + } else { + static CHAIN: Lazy> = Lazy::new(Default::default); + } + } + CHAIN.renameat2(fn_ptr, olddirfd, oldpath, newdirfd, newpath, flags) +} + +trait Renameat2Syscall { + extern "C" fn renameat2( + &self, + fn_ptr: Option<&extern "C" fn(c_int, *const c_char, c_int, *const c_char, c_uint) -> c_int>, + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, + flags: c_uint, + ) -> c_int; +} + +impl_facade!(Renameat2SyscallFacade, Renameat2Syscall, + renameat2( + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, + flags: c_uint, + ) -> c_int +); + +impl_io_uring!(IoUringRenameat2Syscall, Renameat2Syscall, + renameat2( + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, + flags: c_uint, + ) -> c_int +); + +impl_raw!(RawRenameat2Syscall, Renameat2Syscall, + renameat2( + olddirfd: c_int, + oldpath: *const c_char, + newdirfd: c_int, + newpath: *const c_char, + flags: c_uint, + ) -> c_int +); diff --git a/core/src/syscall/unix/write.rs b/core/src/syscall/unix/write.rs index a06fde6a..5935f679 100644 --- a/core/src/syscall/unix/write.rs +++ b/core/src/syscall/unix/write.rs @@ -41,7 +41,7 @@ impl_io_uring_write!(IoUringWriteSyscall, WriteSyscall, ); impl_nio_write_buf!(NioWriteSyscall, WriteSyscall, - write(fd: c_int, buf: *const c_void, len: size_t, ) -> ssize_t + write(fd: c_int, buf: *const c_void, len: size_t) -> ssize_t ); impl_raw!(RawWriteSyscall, WriteSyscall, diff --git a/hook/src/syscall/unix.rs b/hook/src/syscall/unix.rs index e865143b..c633953e 100644 --- a/hook/src/syscall/unix.rs +++ b/hook/src/syscall/unix.rs @@ -70,6 +70,11 @@ impl_hook!(RMDIR, rmdir(path: *const c_char) -> c_int); impl_hook!(LSEEK, lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t); impl_hook!(LINK, link(src: *const c_char, dst: *const c_char) -> c_int); impl_hook!(UNLINK, unlink(src: *const c_char) -> c_int); +impl_hook!(FSYNC, fsync(fd: c_int) -> c_int); +impl_hook!(MKDIRAT, mkdirat(dirfd: c_int, pathname: *const c_char, mode: mode_t) -> c_int); +impl_hook!(RENAMEAT, renameat(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char) -> c_int); +#[cfg(target_os = "linux")] +impl_hook!(RENAMEAT2, renameat2(olddirfd: c_int, oldpath: *const c_char, newdirfd: c_int, newpath: *const c_char, flags: c_uint) -> c_int); // NOTE: unhook poll due to mio's poller // impl_hook!(POLL, poll(fds: *mut pollfd, nfds: nfds_t, timeout: c_int) -> c_int); diff --git a/open-coroutine/Cargo.toml b/open-coroutine/Cargo.toml index 576084a7..dc948442 100644 --- a/open-coroutine/Cargo.toml +++ b/open-coroutine/Cargo.toml @@ -3,9 +3,9 @@ name = "open-coroutine" version.workspace = true edition.workspace = true authors = ["zhangzicheng@apache.org"] -description = "The open-coroutine is a simple, efficient and generic stackful-coroutine library." +description = "The open-coroutine is a simple, efficient and generic stackfull-coroutine library." repository = "https://github.com/acl-dev/open-coroutine" -keywords = ["coroutine", "fiber", "stackful", "hook"] +keywords = ["coroutine", "fiber", "stackfull", "hook"] categories = ["data-structures", "concurrency", "asynchronous", "web-programming", "wasm"] license.workspace = true readme.workspace = true