您的位置:首页 > 运维架构 > Linux

Linux 2.6.36版本内核分析之schedule()

2013-05-12 15:32 393 查看
/*

* schedule() is the main scheduler function.调度主函数,又称主调度

*/

asmlinkage void__schedschedule(void)

{

struct task_struct *prev, *next;//prev:换出进程标识符,next:换入进程标识符

unsigned long *switch_count;//对prev的进程切换进行计数

struct rq *rq;//运行队列

int cpu;//CPU号

need_resched:

preempt_disable();//关中断

cpu = smp_processor_id();//获取执行prev进程的cpu号

rq = cpu_rq(cpu);//获取cpu号所代表的CPU的运行队列

rcu_note_context_switch(cpu);//

prev = rq->curr;//获取运行队列中当前指向的进程,也是即将被换出的进程,进程状态是什么?

release_kernel_lock(prev);//释放大内核锁

need_resched_nonpreemptible:

schedule_debug(prev);

if (sched_feat(HRTICK))

hrtick_clear(rq);

raw_spin_lock_irq(&rq->lock);

clear_tsk_need_resched(prev);

switch_count = &prev->nivcsw;

if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {

if (unlikely(signal_pending_state(prev->state, prev))) {

prev->state = TASK_RUNNING;

} else {

/*

* If a worker is going to sleep, notify and

* ask workqueue whether it wants to wake up a

* task to maintain concurrency. If so, wake

* up the task.

*/

if (prev->flags & PF_WQ_WORKER) {

struct task_struct *to_wakeup;

to_wakeup = wq_worker_sleeping(prev, cpu);

if (to_wakeup)

try_to_wake_up_local(to_wakeup);

}

deactivate_task(rq, prev, DEQUEUE_SLEEP);

}

switch_count = &prev->nvcsw;

}

pre_schedule(rq, prev);

if (unlikely(!rq->nr_running))

idle_balance(cpu, rq);

put_prev_task(rq, prev);

next = pick_next_task(rq);

if (likely(prev != next)) {

sched_info_switch(prev, next);

perf_event_task_sched_out(prev, next);

rq->nr_switches++;

rq->curr = next;

++*switch_count;

context_switch(rq, prev, next); /* unlocks the rq */

/*

* The context switch have flipped the stack from under us

* and restored the local variables which were saved when

* this task called schedule() in the past. prev == current

* is still correct, but it can be moved to another cpu/rq.

*/

cpu = smp_processor_id();

rq = cpu_rq(cpu);

} else

raw_spin_unlock_irq(&rq->lock);

post_schedule(rq);

if (unlikely(reacquire_kernel_lock(prev)))

goto need_resched_nonpreemptible;

preempt_enable_no_resched();

if (need_resched())

goto need_resched;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: