Linux内核schedule函数分析

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

只有流过血的手指才能弹出世间的绝唱。

Linux内核schedule函数分析

相关文章:

你感兴趣的文章:

标签云: