调度子系统2_核心调度器

//	核心调度器
//		当进程决定让出cpu时调用
//	函数任务:
//		1.禁止内核抢占
//		2.获取本cpu的rq
//		3.取消为当前进程运行的hrtimer
//		4.获取队列锁
//		5.更新队列时钟
//		6.清除当前进程need resched标志
//		7.如果当前进程为非运行状态,并且当前非内核抢占路径
//			7.1 如果当前进程有信号待处理,设置当前进程为就绪状态
//			7.2 否则进程出队rq
//		8.如果当前rq没有可运行进程
//			8.1 通过load balance从其他进程搬进程
//		9.通知调度器类用另一个进程代替当前进程
//		10.通知调度器类选择下一个可运行进程
//		11.如果下一个运行的进程非当前进程
//			11.1 执行进程切换
//		12.否则释放队列锁
//		13.开启内核抢占
//		14.如果当前进程被设置need resched,重复1 
1.1 asmlinkage void __sched schedule(void)
{
	struct task_struct *prev, *next;
	unsigned long *switch_count;
	struct rq *rq;
	int cpu;

need_resched:
	//禁止抢占
	preempt_disable();
	cpu = smp_processor_id();
	//本cpu的rq
	rq = cpu_rq(cpu);
	//当前rq上正在运行的进程
	prev = rq->curr;
	//进程被切换的次数
	switch_count = &prev->nivcsw;

	//取消为当前进程运行的hrtimer
	if (sched_feat(HRTICK))
		hrtick_clear(rq);
	//获取队列锁
	raw_spin_lock_irq(&rq->lock);
	//更新队列时钟
	update_rq_clock(rq);
	//清除当前进程need resched标志
	clear_tsk_need_resched(prev);
	//当前进程非运行状态,并且非内核抢占
	if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
		//当前进程有信号待处理,设置进程为运行态
		if (unlikely(signal_pending_state(prev->state, prev)))
		{
			prev->state = TASK_RUNNING;
		}
		else
		{	//进程出队rq
			deactivate_task(rq, prev, 1);
		}
			
		switch_count = &prev->nvcsw;
	}
	//通知调度器类,即将发生进程切换
	pre_schedule(rq, prev);
	//当前rq没有可运行进程,通过loadbalance从其他cpu的rq搬进程过来
	if (unlikely(!rq->nr_running))
		idle_balance(cpu, rq);
	//通知调度器类用另一个进程代替当前进程
	put_prev_task(rq, prev);
	//通知调度器类选择下一个可运行进程
	next = pick_next_task(rq);
	//切换当前进程
	if (likely(prev != next)) {	
		//统计rq切换次数
		rq->nr_switches++;
		rq->curr = next;
		++*switch_count;
		//切换进程上下文
		context_switch(rq, prev, next); 
		//现在已经是另一个进程在运行
		cpu = smp_processor_id();
		rq = cpu_rq(cpu);
	} else
		raw_spin_unlock_irq(&rq->lock);
	//通知调度器类,完成了进程切换
	post_schedule(rq);
	//开启内核抢占
	preempt_enable_no_resched();
	//如果当前进程需要切换,则再次切换
	if (need_resched())
		goto need_resched;
}

//	通知调度器类,即将进程切换
2.1 static inline void pre_schedule(struct rq *rq, struct task_struct *prev)
{
	if (prev->sched_class->pre_schedule)
		prev->sched_class->pre_schedule(rq, prev);
}

//	通知调度器,完成了进程切换
2.2 static inline void post_schedule(struct rq *rq)
{
	if (rq->post_schedule) {
		unsigned long flags;
		//获取队列锁
		raw_spin_lock_irqsave(&rq->lock, flags);
		if (rq->curr->sched_class->post_schedule)
			rq->curr->sched_class->post_schedule(rq);
		raw_spin_unlock_irqrestore(&rq->lock, flags);
		rq->post_schedule = 0;
	}
}

//	通知调度器类,用另一个进程替换当前进程
3.1 static void put_prev_task(struct rq *rq, struct task_struct *prev)
{
	....
	prev->sched_class->put_prev_task(rq, prev);
}


//	通知调度器类,选择下一个运行的进程
4.1 static inline struct task_struct *pick_next_task(struct rq *rq)
{
	const struct sched_class *class;
	struct task_struct *p;

	//如果rq中进程数等于cfs中进程数,说明没有rt进程,由cfs选出下一个运行的进程
	if (likely(rq->nr_running == rq->cfs.nr_running)) {
		p = fair_sched_class.pick_next_task(rq);
		if (likely(p))
			return p;
	}
	//否则由最高优先级的调度类
	class = sched_class_highest;
	for ( ; ; ) {
		//选择下一个运行进程
		p = class->pick_next_task(rq);
		if (p)
			return p;
		//下一个优先级的调度类
		class = class->next;
	}
}
//	最高优先级调度器类
4.2 #define sched_class_highest (&rt_sched_class)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值