zoukankan      html  css  js  c++  java
  • 调度子系统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)


  • 相关阅读:
    HDOJ 5090 Game with Pearls 二分图匹配
    hdu4360 spfa+分割点
    分布式高级(十三)Docker Container之间的数据共享
    [Ramda] Get a List of Unique Values From Nested Arrays with Ramda (flatMap --> Chain)
    [Ramda] Create an Array From a Seed Value with Ramda's unfold
    [Flow] Declare types for application
    [Flow] The Fundamentals of Flow
    [Angular] Some performance tips
    [Ramda] Rewrite if..else with Ramda ifElse
    [SVG] Add an SVG as an Embedded Background Image
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3469107.html
Copyright © 2011-2022 走看看