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

来源:互联网 发布:淘宝的oz轮毂 编辑:程序博客网 时间:2024/06/06 14:05

/*
* 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;
}

 

原创粉丝点击