| Crates.io | vsched_base_task |
| lib.rs | vsched_base_task |
| version | 0.1.0 |
| created_at | 2026-01-21 03:52:46.143304+00 |
| updated_at | 2026-01-21 03:52:46.143304+00 |
| description | vsched的依赖库,定义基本任务类型 |
| homepage | https://github.com/rosy233333/vsched |
| repository | https://github.com/rosy233333/vsched |
| max_upload_size | |
| id | 2058235 |
| size | 45,060 |

最重要的模块为vsched和task_management。
vsched:实现为vdso共享库。其功能包括:
BaseTask(其中,协程的定义需要外部提供alloc_stack和coroutine_schedule函数,因为不同地址空间的这些函数可能有不同的实现)task_management:实现为普通库。其功能包括:
TaskExtFuture(因为vDSO的接口只能为普通函数,因此协程的相应接口需要在vDSO外部加一层Future包装)alloc_stack和coroutine_schedule函数join操作(如果是使用相同辅助库的任务,就可以互相join)base_task和scheduler为vsched的依赖库。base_task 定义了BaseTask任务结构,scheduler 定义了多种任务无关的调度器,同时也为任务做了一层包装以保存调度信息。
user_test 为用户态的测试代码,测试了 init、spawn、yield、wait、multi_thread,以及一个覆盖所有内容的all测例。
任务数据结构如下图:

TaskInnerExt:在task_management中定义,对vsched不可见。主要包括用于退出和join的退出代码和退出等待队列,以及线程入口点和Future(协程上下文)。
TaskInner(的其它字段):在base_task中定义,对vsched和task_management均可见。主要包括任务状态、使用的栈和线程上下文。
Task:在scheduler中定义,相较于TaskInner增加了调度器信息。
TaskRef:在scheduler中定义,在vsched中使用的任务指针。不管理引用计数。
ArcTaskRef:在task_management中定义,在task_management中使用的任务指针。管理任务的引用计数。ArcTaskRef通过Arc::into_raw转化为TaskRef(引用计数不变)并放入调度器。当任务退出时,再转化回ArcTaskRef,释放该引用计数。
由于vDSO对API的限制,在任务实际切换时采用了“线程切换在vsched中进行,协程切换在task_management中进行”的策略。但与任务切换相关的设置任务状态与调度器状态的过程,都需要两个模块配合完成。
协程的调度循环为task_management::task::coroutine_schedule函数。
具体的任务切换与阻塞流程如下:
线程 -> 线程:
vsched::api::yield_now -> vsched::sched::yield_current: 先维护就绪队列,再调用resched -> vsched::sched::resched -> vsched::sched::switch_to -> (*prev_ctx_ptr).switch_to(&*next_ctx_ptr): 真正的上下文切换过程
线程 -> 协程:
同上,但是在vsched::sched::switch_to函数中,在上下文切换前,调用next_task.set_kstack(next_task: TaskRef) -> base_task::TaskInner::set_kstack: 根据协程的alloc_stack_fn字段指向的函数分配内核栈;根据协程的coroutine_schedule字段指向的函数设置任务上下文的入口点。
协程 -> 线程:
user_test::vsched::yield_now_f -> YieldFuture::new().await -> user_test::vsched::YieldFuture::poll: 先调用vsched::api::yield_f仅维护就绪队列和任务状态不执行实际切换,再返回poll::Pending至user_test::task::coroutine_schedule -> user_test::task::coroutine_schedule: 先通过vsched::api::current获取下一个要执行的任务,再通过(*prev_ctx_ptr).switch_to(&*next_ctx_ptr)执行上下文切换。
协程 -> 协程:
同上,但是在user_test::task::coroutine_schedule函数中,在上下文切换前,将自己已用完的栈传递给下一个协程。并且,不进行线程式的上下文切换,而是直接回到循环开始,运行下一个协程的Future::poll。
线程的阻塞:
user_test::wait_queue::WaitQueue::wait -> user_test::vsched::blocked_resched: 先将任务加入阻塞队列,再调用vsched_apis::resched -> vsched::api::resched -> vsched::sched::resched,之后同任务切换过程
协程的阻塞:
user_test::wait_queue::WaitQueue::wait -> BlockedReschedFuture::new(self).await -> user_test::vsched::BlockedReschedFuture::poll: 先将任务加入阻塞队列,之后调用vsched_apis::resched_f仅维护就绪队列不执行实际切换,之后的切换过程同协程的切换。
(协程的阻塞没有使用Waker相关机制,且user_test::task::coroutine_schedule函数中使用的Waker也是Waker::noop,因此该协程调度器不支持基于Waker的协程阻塞。)
测试命令:
UTEST=[测例名称,即为user_test/src/bin中的文件名] make utest
或运行test.sh,会测试yield、wait和smp三项。