调度器
获取当前任务
c
yr_task_t* yr_sched_get_current(void);获取当前正在运行的任务对象指针。
- 返回值
- 当前运行任务指针
- 说明
- 在任务上下文中可将其理解为“当前线程”
- 在内核尚未启动前,返回值可能为
NULL
初始化调度器
c
void yr_sched_init(void);初始化调度器内部状态。
- 行为
- 清空当前任务指针
- 清空就绪优先级位图
- 初始化每个优先级对应的就绪链表
- 初始化僵尸任务链表
- 说明
- 一般由
yr_kernel_init()内部调用
- 一般由
启动调度器
c
void yr_sched_start(void);启动调度器并切换到第一个任务。
- 行为
- 从就绪位图中找出当前最高优先级
- 取出该优先级链表中的第一个任务作为首任务
- 将其状态置为
RUNNING - 调用移植层接口切换到首任务
- 说明
- 这是从“初始化阶段”进入“多任务运行阶段”的关键步骤
执行一次任务切换
c
void yr_sched_switch(void);根据当前就绪情况执行一次任务切换。
- 行为
- 重新计算最高优先级就绪任务
- 若目标任务与当前任务相同,则直接返回
- 若目标任务不同,则更新任务状态并调用移植层执行切换
- 说明
- 该函数既可由任务 API 间接触发,也可由超时唤醒等内核路径触发
插入就绪任务
c
yr_err_t yr_sched_insert_task( yr_task_t* task);将一个任务插入调度器的就绪队列。
- 参数
- task 待插入任务对象指针
- 行为
- 将任务插入到其当前优先级对应链表的尾部
- 更新就绪优先级位图
- 返回值
- 返回 YR_OK 表示成功,否则失败,见返回值定义
- 说明
- 任务被唤醒、启动或从阻塞态恢复时通常会走这条路径
移出就绪任务
c
yr_err_t yr_sched_remove_task( yr_task_t* task);将一个任务从调度器的就绪队列中移除。
- 参数
- task 待移除任务对象指针
- 行为
- 将任务从对应优先级链表中删除
- 若该优先级已经没有其它就绪任务,则清除位图中的对应 bit
- 返回值
- 返回 YR_OK 表示成功,否则失败,见返回值定义
- 说明
- 任务阻塞、挂起、删除时通常会先从调度器中移除
当前任务主动让出处理器
c
void yr_sched_yield(void);让当前任务主动让出 CPU。
- 行为
- 将当前任务移动到同优先级就绪链表的后部
- 若同优先级没有其它任务,则不会发生实际切换
- 若存在同优先级其它任务,则随后触发一次调度
- 说明
- 常用于同优先级任务之间主动轮转
yr_task_sleep_ticks(0)的效果与“立即触发一次调度”接近
调度器示例
以下是调度器在常见运行路径中的典型工作方式:
- 任务启动
yr_task_start()调用yr_sched_insert_task()将任务放入就绪队列
- 任务阻塞
yr_task_sleep_ticks()或 IPC 等待会先调用yr_sched_remove_task()
- 时间片耗尽
yr_tick_update()中会调用yr_sched_yield()让同优先级任务轮转
- 高优先级任务被唤醒
- 内核会在恢复该任务后进一步调用
yr_sched_switch(),使其尽快运行
- 内核会在恢复该任务后进一步调用