歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核schedule函數分析

Linux內核schedule函數分析

日期:2017/2/28 16:16:47   编辑:Linux內核

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

Copyright © Linux教程網 All Rights Reserved