asmlinkage void schedule(void){task_t *prev, *next;runqueue_t *rq;prio_array_t *array;struct list_head *queue;int idx;
#判断是否调度发生在中断上下文,,如果是就出错;在LINUX的中断中是不允许发生调度的
if (unlikely(in_interrupt())) BUG();
need_resched:
preempt_disable();prev = current;rq = this_rq();
release_kernel_lock(prev, smp_processor_id());prepare_arch_schedule(prev);prev->sleep_timestamp = jiffies;spin_lock_irq(&rq->lock);
if (unlikely(preempt_get_count() & PREEMPT_ACTIVE)) goto pick_next_task;
switch (prev->state) {case TASK_INTERRUPTIBLE: if (unlikely(signal_pending(prev))) { prev->state = TASK_RUNNING; break; }default: deactivate_task(prev, rq);case TASK_RUNNING: ;}pick_next_task:if (unlikely(!rq->nr_running)) {#if CONFIG_SMP load_balance(rq, 1); if (rq->nr_running) goto pick_next_task;#endif next = rq->idle; rq->expired_timestamp = 0; goto switch_tasks;}
array = rq->active;if (unlikely(!array->nr_active)) { rq->active = rq->expired; rq->expired = array; array = rq->active; rq->expired_timestamp = 0;}
idx = sched_find_first_bit(array->bitmap);queue = array->queue + idx;next = list_entry(queue->next, task_t, run_list);
switch_tasks:prefetch(next);clear_tsk_need_resched(prev);
if (likely(prev != next)) { rq->nr_switches++; rq->curr = next; prepare_arch_switch(rq);
TRACE_SCHEDCHANGE(prev, next);
prev = context_switch(prev, next); barrier(); rq = this_rq(); finish_arch_switch(rq);} else spin_unlock_irq(&rq->lock);finish_arch_schedule(prev);
reacquire_kernel_lock(current);preempt_enable_no_resched();if (need_resched()) goto need_resched;}
只有流过血的手指才能弹出世间的绝唱。