调度子系统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)


你可能感兴趣的:(调度器)