【Linux】【Kernel】【调度】
代码路径
- kernel/sched/core.c
- arch/arm64/kernel/entry.S
函数
schedule
/** 位于 kernel/sched/core.c **/
asmlinkage __visible void __sched schedule(void);
static void __sched notrace __schedule(bool preempt);
驱动调度器进入__schedule
,有以下的几种方式:
- 显式阻塞:互斥锁、信号量、等待队列等
- 在中断和用户空间返回路径上检查
TIF_NEED_RESCHED
标志 (这个可以留意arch/arm64/kernel/entry.S
中的el1_irq
定义) - 如果内核是可抢占的(
CONFIG_PREEMPT=y
): -
- 在系统调用或异常上下文中,在下一次最外层的
preempt_enable()
处调用。(可能就是wake_up()
的spin_unlock()
之后!)
- 在系统调用或异常上下文中,在下一次最外层的
-
- 在中断上下文中,从中断处理程序返回到可抢占的上下文。
- 如果内核不可抢占(
CONFIG_PREEMPT
没有设置),则在下一次出现以下情况时调用: -
cond_resched()
调用
-
- 显式的
schedule()
调用
- 显式的
-
- 从系统调用或异常返回到用户空间;
-
- 从中断处理程序返回到用户空间;
必须在禁用抢占的条件下进行__schedule
调度算法的触发点
/** kernel/sched/core.c **/
void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags);
Linux 内核调度相关代码解析
-
deactivate_task(struct rq *rq, struct task_struct *p, int flags)
该函数用于将任务标记为非活跃状态并执行相应的操作。 -
ttwu_do_wakeup(struct rq *rq, struct task_struct *p, int wake_flags, struct rq_flags *rf)
该函数用于将任务标记为可运行状态并执行唤醒-抢占操作。 -
wq_worker_sleeping(struct task_struct *task)
该函数用于处理工作线程进入睡眠状态的情况。 -
try_to_wake_up_local(struct task_struct *p, struct rq_flags *rf)
该函数尝试唤醒本地任务,并在运行队列锁定状态下执行。 -
enqueue_task(struct rq *rq, struct task_struct *p, int flags)
该函数用于将任务加入运行队列,并执行相应的操作。