| title | Monitor总览 |
|---|---|
| date | 2025-01-02 00:35:00 -0800 |
| author | loongs-zhang |
English | 中文
preemptive特性目前支持以下targets:
| ELF (Linux, BSD, bare metal, etc) | Darwin (macOS, iOS, etc) | Windows | |
|---|---|---|---|
x86_64 |
✅ | ✅ | ✅ |
x86 |
✅ | ❌ | ✅ |
AArch64 |
✅ | ✅ | ❌ |
ARM |
✅ | ❌ | ❌ |
RISC-V |
✅ | ❌ | ❌ |
LoongArch64 |
✅ | ❌ | ❌ |
✅ 已测试且稳定;
open-coroutine-core中使用preemptive特性,你必须学习Hook总览。
use open_coroutine_core::co;
use open_coroutine_core::common::constants::CoroutineState;
use open_coroutine_core::coroutine::Coroutine;
fn main() -> std::io::Result<()> {
// 模拟最极端的死循环,如果未启用preemptive特性,协程恢复后将一直卡在死循环中
let mut coroutine: Coroutine<(), (), ()> = co!(|_, ()| { loop {} })?;
assert_eq!(CoroutineState::Suspend((), 0), coroutine.resume()?);
// 如果未启用抢占特性,将永远不会到达此处
assert_eq!(CoroutineState::Suspend((), 0), coroutine.state());
Ok(())
}在调用Coroutine::resume_with后,协程可能会长时间占用调度线程,从而拖慢由该调度线程调度的其他协程。协程在两种情况下会长时间占用调度线程:陷入重度计算或系统调用。为了解决陷入重度计算的问题,我们引入抢占式调度,它会自动挂起长时间执行的协程,并允许其他协程执行。
monitor是open-coroutine-core的一个模块,它实现了preemptive特性,这允许协程在长时间运行后被抢占。
sequenceDiagram
actor 用户线程
participant 协程
participant MonitorListener
participant Monitor线程
用户线程 ->>+ 协程: Coroutine::resume_with
协程 ->>+ MonitorListener: Listener::on_state_changed
MonitorListener ->>+ Monitor线程: Monitor::submit
Monitor线程 ->>+ Monitor线程: libc::sigaction
alt 发生抢占
协程 ->> 协程: 协程状态变为Running超过10ms
Monitor线程 ->>+ 用户线程: libc::pthread_kill
用户线程 ->>+ 用户线程: libc::pthread_sigmask
用户线程 ->>+ 协程: 挂起协程,具体实现可查看sigurg_handler
协程 ->> 用户线程: 协程已被抢占
else 未发生抢占
协程 ->> 协程: 协程状态变为Suspend/Syscall/Complete/Error
协程 ->>+ MonitorListener: Listener::on_state_changed
MonitorListener ->>+ Monitor线程: Monitor::remove
Monitor线程 ->>+ MonitorListener: 返回
MonitorListener ->>+ 协程: 返回
协程 ->> 用户线程: 返回
end