linux内核中优先级最高,linux内核调度算法(1)--快速找到最高优先级进程

asmlinkagevoid__sched schedule(void)

{

long*switch_count;

task_t *prev, *next;

runqueue_t *rq;

prio_array_t *array;

structlist_head *queue;

unsigned longlongnow;

unsigned longrun_time;

intcpu, idx;

/*

* Test if we are atomic.  Since do_exit() needs to call into

* schedule() atomically, we ignore that path for now.

* Otherwise, whine if we are scheduling when we should not be.

*/

if(likely(!(current->exit_state & (EXIT_DEAD | EXIT_ZOMBIE)))) {先看看当前运行进程的状态

if(unlikely(in_atomic())) {

printk(KERN_ERR "scheduling while atomic: "

"%s/0x%08x/%d\n",

current->comm, preempt_count(), current->pid);

dump_stack();

}

}

profile_hit(SCHED_PROFILING, __builtin_return_address(0));

need_resched:

preempt_disable();

prev = current;

release_kernel_lock(prev);

need_resched_nonpreemptible:

rq = this_rq();      这行找到这个CPU对应的runqueue,再次强调,每个CPU有一个自己的runqueue

/*

* The idle thread is not allowed to schedule!

* Remove this check after it has been exercised a bit.

*/

if(unlikely(current == rq->idle) && current->state != TASK_RUNNING) {

printk(KERN_ERR "bad: scheduling from the idle thread!\n");

dump_stack();

}

schedstat_inc(rq, sched_cnt);

now = sched_clock();

if(likely(now - prev->timestamp

run_time = now - prev->timestamp;

else

run_time = NS_MAX_SLEEP_AVG;

/*

* Tasks with interactive credits get charged less run_time

* at high sleep_avg to delay them losing their interactive

* status

*/

if(HIGH_CREDIT(prev))

run_time /= (CURRENT_BONUS(prev) ? : 1);

spin_lock_irq(&rq->lock);

if(unlikely(current->flags & PF_DEAD))

current->state = EXIT_DEAD;

/*

* if entering off of a kernel preemption go straight

* to picking the next task.

*/

switch_count = &prev->nivcsw;

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

switch_count = &prev->nvcsw;

if(unlikely((prev->state & TASK_INTERRUPTIBLE) &&

unlikely(signal_pending(prev))))

prev->state = TASK_RUNNING;

else{

if(prev->state == TASK_UNINTERRUPTIBLE)

rq->nr_uninterruptible++;

deactivate_task(prev, rq);

}

}

cpu = smp_processor_id();

if(unlikely(!rq->nr_running)) {

go_idle:

idle_balance(cpu, rq);

if(!rq->nr_running) {

next = rq->idle;

rq->expired_timestamp = 0;

wake_sleeping_dependent(cpu, rq);

/*

* wake_sleeping_dependent() might have released

* the runqueue, so break out if we got new

* tasks meanwhile:

*/

if(!rq->nr_running)

gotoswitch_tasks;

}

} else{

if(dependent_sleeper(cpu, rq)) {

next = rq->idle;

gotoswitch_tasks;

}

/*

* dependent_sleeper() releases and reacquires the runqueue

* lock, hence go into the idle loop if the rq went

* empty meanwhile:

*/

if(unlikely(!rq->nr_running))

gotogo_idle;

}

array = rq->active;

if(unlikely(!array->nr_active)) {       上面说过的,需要重新计算时间片时,就用已经计算好的expired队列了

/*

* Switch the active and expired arrays.

*/

schedstat_inc(rq, sched_switch);

rq->active = rq->expired;

rq->expired = array;

array = rq->active;

rq->expired_timestamp = 0;

rq->best_expired_prio = MAX_PRIO;

} else

schedstat_inc(rq, sched_noswitch);

idx = sched_find_first_bit(array->bitmap);         找到优先级最高的队列

queue = array->queue + idx;

next = list_entry(queue->next, task_t, run_list);

if(!rt_task(next) && next->activated > 0) {

unsigned longlongdelta = now - next->timestamp;

if(next->activated == 1)

delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;

array = next->array;

dequeue_task(next, array);

recalc_task_prio(next, next->timestamp + delta);

enqueue_task(next, array);

}

next->activated = 0;

switch_tasks:

if(next == rq->idle)

schedstat_inc(rq, sched_goidle);

prefetch(next);

clear_tsk_need_resched(prev);

rcu_qsctr_inc(task_cpu(prev));

prev->sleep_avg -= run_time;

if((long)prev->sleep_avg <= 0) {

prev->sleep_avg = 0;

if(!(HIGH_CREDIT(prev) || LOW_CREDIT(prev)))

prev->interactive_credit--;

}

prev->timestamp = prev->last_ran = now;

sched_info_switch(prev, next);

if(likely(prev != next)) {              表面现在正在执行的进程,不是选出来的优先级最高的进程

next->timestamp = now;

rq->nr_switches++;

rq->curr = next;

++*switch_count;

prepare_arch_switch(rq, next);

prev = context_switch(rq, prev, next);              所以需要完成进程上下文切换,把之前的进程信息CACHE住

barrier();

finish_task_switch(prev);

} else

spin_unlock_irq(&rq->lock);

prev = current;

if(unlikely(reacquire_kernel_lock(prev)

gotoneed_resched_nonpreemptible;

preempt_enable_no_resched();

if(unlikely(test_thread_flag(TIF_NEED_RESCHED)))

gotoneed_resched;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值