Chinaunix首页 | 论坛 | 博客
  • 博客访问: 90475
  • 博文数量: 16
  • 博客积分: 1113
  • 博客等级: 少尉
  • 技术积分: 170
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-31 13:36
文章分类

全部博文(16)

文章存档

2011年(4)

2010年(12)

分类: 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字段指向活动进程链表

}

阅读(3850) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~