Skip to content

调度器

获取当前任务

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 待插入任务对象指针
  • 行为
    • 将任务插入到其当前优先级对应链表的尾部
    • 更新就绪优先级位图
  • 返回值
  • 说明
    • 任务被唤醒、启动或从阻塞态恢复时通常会走这条路径

移出就绪任务

c
yr_err_t yr_sched_remove_task( yr_task_t* task);

将一个任务从调度器的就绪队列中移除。

  • 参数
    • task 待移除任务对象指针
  • 行为
    • 将任务从对应优先级链表中删除
    • 若该优先级已经没有其它就绪任务,则清除位图中的对应 bit
  • 返回值
  • 说明
    • 任务阻塞、挂起、删除时通常会先从调度器中移除

当前任务主动让出处理器

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(),使其尽快运行