From 0281a61408715069eb0c20f0ab9c59a8c51dcc85 Mon Sep 17 00:00:00 2001 From: hailang Date: Wed, 12 Apr 2023 23:53:00 +0800 Subject: [PATCH] impl preemptive schedule --- .github/workflows/ci.yml | 4 --- examples/change_pc.rs | 73 ---------------------------------------- src/monitor.rs | 68 +++++++++++-------------------------- 3 files changed, 20 insertions(+), 125 deletions(-) delete mode 100644 examples/change_pc.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f7705c..cc5045d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,8 +66,6 @@ jobs: args: --release --all --no-run - name: Run cargo release test run: sudo bash -c "sudo -u runner RUSTUP_TOOLCHAIN=${{ matrix.rust }} RUST_BACKTRACE=1 /home/runner/.cargo/bin/cargo test --release --all" - - name: Run cargo release change_pc - run: sudo bash -c "sudo -u runner RUSTUP_TOOLCHAIN=${{ matrix.rust }} RUST_BACKTRACE=1 /home/runner/.cargo/bin/cargo run --example change_pc --release" - name: Run cargo release preemptive example run: sudo bash -c "sudo -u runner RUSTUP_TOOLCHAIN=${{ matrix.rust }} RUST_BACKTRACE=1 /home/runner/.cargo/bin/cargo run --example preemptive --release --features preemptive-schedule" @@ -100,7 +98,5 @@ jobs: args: --release --all --no-run - name: Run cargo release test run: sudo bash -c "sudo -u runner RUSTUP_TOOLCHAIN=${{ matrix.rust }} RUST_BACKTRACE=1 /Users/runner/.cargo/bin/cargo test --release --all" - - name: Run cargo release change_pc - run: sudo bash -c "sudo -u runner RUSTUP_TOOLCHAIN=${{ matrix.rust }} RUST_BACKTRACE=1 /Users/runner/.cargo/bin/cargo run --example change_pc --release" - name: Run cargo release preemptive example run: sudo bash -c "sudo -u runner RUSTUP_TOOLCHAIN=${{ matrix.rust }} RUST_BACKTRACE=1 /Users/runner/.cargo/bin/cargo run --example preemptive --release --features preemptive-schedule" diff --git a/examples/change_pc.rs b/examples/change_pc.rs deleted file mode 100644 index 67c5853..0000000 --- a/examples/change_pc.rs +++ /dev/null @@ -1,73 +0,0 @@ -use libc::{sigaction, siginfo_t, ucontext_t, SA_NODEFER, SA_RESTART, SA_SIGINFO, SIGINT}; -use std::os::unix::thread::JoinHandleExt; - -static mut RUN: bool = true; - -unsafe extern "C" fn yields() { - println!("yielded after signal_handler returned"); - RUN = false; -} - -unsafe extern "C" fn signal_handler(signum: i32, _siginfo: &siginfo_t, context: &mut ucontext_t) { - cfg_if::cfg_if! { - if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "x86_64", - ))] { - context.uc_mcontext.gregs[libc::REG_RIP as usize] = yields as i64; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "x86", - ))] { - context.uc_mcontext.gregs[libc::REG_EIP as usize] = yields as i32; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "aarch64", - ))] { - context.uc_mcontext.pc = yields as libc::c_ulong; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "arm", - ))] { - context.uc_mcontext.arm_pc = yields as libc::c_ulong; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - any(target_arch = "riscv64", target_arch = "riscv32"), - ))] { - context.uc_mcontext.__gregs[libc::REG_PC] = yields as libc::c_ulong; - } else if #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] { - (*context.uc_mcontext).__ss.__pc = yields as u64; - } else if #[cfg(all(target_vendor = "apple", target_arch = "x86_64"))] { - (*context.uc_mcontext).__ss.__rip = yields as u64; - } else { - compile_error!("Unsupported platform"); - } - } - println!("Received signal {}", signum); -} - -//RUSTFLAGS="--emit asm" cargo build --example change_pc --release 获取优化后的汇编代码 -fn main() { - let handler = std::thread::spawn(|| unsafe { - let mut sa: sigaction = std::mem::zeroed(); - sa.sa_sigaction = signal_handler as usize; - libc::sigemptyset(&mut sa.sa_mask); - sa.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER; - if sigaction(SIGINT, &sa, std::ptr::null_mut()) == -1 { - println!("Failed to register handler for SIGINT"); - return; - } - - while RUN { - println!("Waiting for signal..."); - libc::sleep(1); - } - }); - let pthread = handler.as_pthread_t(); - unsafe { - libc::sleep(1); - libc::pthread_kill(pthread, SIGINT); - libc::sleep(1); - handler.join().unwrap(); - } -} diff --git a/src/monitor.rs b/src/monitor.rs index 38c1ec4..f2f1ff3 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -35,10 +35,7 @@ impl Monitor { let mut act: libc::sigaction = std::mem::zeroed(); act.sa_sigaction = sigurg_handler; assert_eq!(0, libc::sigaddset(&mut act.sa_mask, Monitor::signum())); - // SA_NODEFER:默认情况下,当信号函数运行时,内核将阻塞(不可重入)给定的信号, - // 直至当次处理完毕才开始下一次的信号处理。但是设置该标记之后,那么信号函数 - // 将不会被阻塞,此时需要注意函数的可重入安全性。 - act.sa_flags = libc::SA_SIGINFO | libc::SA_RESTART | libc::SA_NODEFER; + act.sa_flags = libc::SA_RESTART; assert_eq!( 0, libc::sigaction(Monitor::signum(), &act, std::ptr::null_mut()) @@ -49,52 +46,27 @@ impl Monitor { fn new() -> Self { #[cfg(all(unix, feature = "preemptive-schedule"))] { - extern "C" fn yields() { - if let Some(s) = crate::coroutine::suspender::Suspender::<(), ()>::current() { - s.suspend(); - } - } #[allow(clippy::fn_to_numeric_cast)] - unsafe extern "C" fn sigurg_handler( - _signal: libc::c_int, - _siginfo: &libc::siginfo_t, - context: &mut libc::ucontext_t, - ) { + unsafe extern "C" fn sigurg_handler(_signal: libc::c_int) { // invoke by Monitor::signal() - // 在本方法结束后调用yields - cfg_if::cfg_if! { - if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "x86_64", - ))] { - context.uc_mcontext.gregs[libc::REG_RIP as usize] = yields as i64; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "x86", - ))] { - context.uc_mcontext.gregs[libc::REG_EIP as usize] = yields as i32; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "aarch64", - ))] { - context.uc_mcontext.pc = yields as libc::c_ulong; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - target_arch = "arm", - ))] { - context.uc_mcontext.arm_pc = yields as libc::c_ulong; - } else if #[cfg(all( - any(target_os = "linux", target_os = "android"), - any(target_arch = "riscv64", target_arch = "riscv32"), - ))] { - context.uc_mcontext.__gregs[libc::REG_PC] = yields as libc::c_ulong; - } else if #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] { - (*context.uc_mcontext).__ss.__pc = yields as u64; - } else if #[cfg(all(target_vendor = "apple", target_arch = "x86_64"))] { - (*context.uc_mcontext).__ss.__rip = yields as u64; - } else { - compile_error!("Unsupported platform"); - } + if let Some(s) = crate::coroutine::suspender::Suspender::<(), ()>::current() { + //获取当前信号屏蔽集 + let mut current_mask = libc::sigset_t::default(); + assert_eq!( + 0, + libc::pthread_sigmask(libc::SIG_BLOCK, std::ptr::null(), &mut current_mask), + ); + //删除对Monitor::signum()信号的屏蔽,使信号处理函数即使在处理中,也可以再次进入信号处理函数 + assert_eq!(0, libc::sigdelset(&mut current_mask, Monitor::signum())); + assert_eq!( + 0, + libc::pthread_sigmask( + libc::SIG_SETMASK, + ¤t_mask, + std::ptr::null_mut() + ) + ); + s.suspend(); } } Monitor::register_handler(sigurg_handler as libc::sighandler_t);