全部博文(16)
分类: LINUX
2010-08-18 17:29:53
现在进程1所需要的我们都已经创建好了。可以说是万事俱备只欠东风!
那么怎么能让进程1运行呢,我们必须把进程1的进程描述符插入到cpu的活动运行队列中去,这样只要再调用schedule()那么进程1便可运行啦!!
废话少说马上进入wake_up_new_task()函数!
void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
{
把新创建进程添加到cpu运行对中中区
unsigned long flags;
int this_cpu, cpu;
runqueue_t *rq, *this_rq;
rq = task_rq_lock(p, &flags);
static inline runqueue_t *task_rq_lock(task_t *p, unsigned long *flags)
__acquires(rq->lock)
{
struct runqueue *rq;
repeat_lock_task:
local_irq_save(*flags);
rq = task_rq(p);
#define task_rq(p) cpu_rq(task_cpu(p))
#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
取得每cpu变量per_cpu_runqueues本地拷贝的地址
spin_lock(&rq->lock);
if (unlikely(rq != task_rq(p))) {
spin_unlock_irqrestore(&rq->lock, *flags);
goto repeat_lock_task;
}
return rq;
}
锁住运行队列结构。并获得cpu运行队列指针!
cpu = task_cpu(p);
static inline unsigned int task_cpu(const struct task_struct *p)
{
return p->thread_info->cpu;
}
获得新创建进程的cpu 编号!
this_cpu = smp_processor_id();
获得当前cpu编号
BUG_ON(p->state != TASK_RUNNING);
/*
* We decrease the sleep average of forking parents
* and children as well, to keep max-interactive tasks
* from forking tasks that are max-interactive. The parent
* (current) is done further down, under its lock.
*/
p->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(p) *
CHILD_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
计算进程的平均睡眠值
p->prio = effective_prio(p);
设置进程的动态优先权(100-139)
进程的静态优先级static_prio用于计算进程的时间片,而动态优先级作为调度器选择合适的进程的依据!
static int effective_prio(task_t *p)
{
int bonus, prio;
if (rt_task(p))
return p->prio;
首先判断是否为实时进程!(prio<100)
bonus = CURRENT_BONUS(p) - MAX_BONUS / 2;
获得创建进程的奖惩
prio = p->static_prio - bonus;
if (prio < MAX_RT_PRIO)
prio = MAX_RT_PRIO;
if (prio > MAX_PRIO-1)
prio = MAX_PRIO-1;
return prio;
}
if (likely(cpu == this_cpu)) {
if (!(clone_flags & CLONE_VM)) {
/*
* The VM isn't cloned, so we're in a good position to
* do child-runs-first in anticipation of an exec. This
* usually avoids a lot of COW overhead.
*/
if (unlikely(!current->array))
__activate_task(p, rq);
else {
p->prio = current->prio;
list_add_tail(&p->run_list, ¤t->run_list);
p->array = current->array;
p->array->nr_active++;
rq->nr_running++;
}
set_need_resched();
} else
/* Run child last */
__activate_task(p, rq);
添加到runqueue中
/*
* We skip the following code due to cpu == this_cpu
*
* task_rq_unlock(rq, &flags);
* this_rq = task_rq_lock(current, &flags);
*/
this_rq = rq;
} else {
this_rq = cpu_rq(this_cpu);
/*
* Not the local CPU - must adjust timestamp. This should
* get optimised away in the !CONFIG_SMP case.
*/
p->timestamp = (p->timestamp - this_rq->timestamp_last_tick)
+ rq->timestamp_last_tick;
__activate_task(p, rq);
if (TASK_PREEMPTS_CURR(p, rq))
resched_task(rq->curr);
/*
* Parent and child are on different CPUs, now get the
* parent runqueue to update the parent's ->sleep_avg:
*/
task_rq_unlock(rq, &flags);
this_rq = task_rq_lock(current, &flags);
}
current->sleep_avg = JIFFIES_TO_NS(CURRENT_BONUS(current) *
PARENT_PENALTY / 100 * MAX_SLEEP_AVG / MAX_BONUS);
task_rq_unlock(this_rq, &flags);
}
static inline void __activate_task(task_t *p, runqueue_t *rq)
{
enqueue_task(p, rq->active);
rq->nr_running++;
更新队列中可运行进程数!
}
static void enqueue_task(struct task_struct *p, prio_array_t *array)
{
sched_info_queued(p);
list_add_tail(&p->run_list, array->queue + p->prio);
根据进程的动态优先级,把进程描述符添加到活动链表中!
__set_bit(p->prio, array->bitmap);
根据prio 把active链表中相应进程位图置1!位数代表优先级,表示此优先级有活动的进程!schedule()函数正是根据位图中的哪位是1,到相应数组链表中去选择下一个要运行的进程!
array->nr_active++;
更新优先级链表中可运行进程数目!
p->array = array;
进程描述符中的array字段指向活动进程链表
}