免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1889 | 回复: 0
打印 上一主题 下一主题

try_to_wake_up代码分析 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-21 15:50 |只看该作者 |倒序浏览
The try_to_wake_up( ) function awakes a sleeping or stopped process by setting its state to TASK_RUNNING and inserting it into the runqueue of the local CPU.
    The function receives as its parameters:
1. The descriptor pointer (p) of the process to be awakened
2. A mask of the process states (state) that can be awakened(要唤醒的进程状态集)
3. A flag (sync) that forbids the awakened process to preempt the process currently running on the local CPU
(如果sync为1则表示禁止唤醒进程p抢占当前进程)
static int try_to_wake_up(task_t * p, unsigned int state, int sync)
{
    int cpu, this_cpu, success = 0;
    unsigned long flags;
    long old_state;
    runqueue_t *rq;
#ifdef CONFIG_SMP
    unsigned long load, this_load;
    struct sched_domain *sd;
    int new_cpu;
#endif
1. 关闭本地中断并给本地可执行队列rq加锁
Invokes the task_rq_lock( ) function to disable local interrupts and to acquire the lock of the runqueue rq owned by the CPU that was last executing the process (it could be different from the local CPU). The logical number of that CPU is stored in the p->thread_info->cpu field.
|----------------------------------|
|   rq = task_rq_lock(p, &flags);  |
|----------------------------------|
2. 如果当前进程状态p->state不在要唤醒的进程状态集中,则不能唤醒该进程
Checks if the state of the process p->state belongs to the mask of states state passed as argument to the function; if this is not the case, it jumps to step 9 to terminate the function.
|----------------------------------|
|   old_state = p->state;          |
|   if (!(old_state & state))      |
|       goto out;                  |
|----------------------------------|
3. 如果当前进程本身就在可执行队列中,则无需唤醒本进程
If the p->array field is not NULL, the process already belongs to a runqueue; therefore, it jumps to step 8.
|----------------------------------|
|   if (p->array)                  |
|       goto out_running;          |
|----------------------------------|
task_cpu(p)返回当前进程p所使用的CPU编号(p所归属的runqueue所在的CPU编号)
|----------------------------------|
|   cpu = task_cpu(p);             |
|   this_cpu = smp_processor_id(); |
|----------------------------------|
4. 多处理器系统:
--------------------------------------------------------------------------------
#ifdef CONFIG_SMP
    if (unlikely(task_running(rq, p)))
        goto out_activate;
#ifdef CONFIG_SCHEDSTATS
    schedstat_inc(rq, ttwu_cnt);
    if (cpu == this_cpu) {
        schedstat_inc(rq, ttwu_local);
    } else {
        for_each_domain(this_cpu, sd) {
            if (cpu_isset(cpu, sd->span)) {
                schedstat_inc(sd, ttwu_wake_remote);
                break;
            }
        }
    }
#endif
    new_cpu = cpu;
    if (cpu == this_cpu || unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
        goto out_set_cpu;
    load = source_load(cpu);
    this_load = target_load(this_cpu);
    if (sync)
        this_load -= SCHED_LOAD_SCALE;
    if (load  SCHED_LOAD_SCALE/2)
        goto out_set_cpu;
    new_cpu = this_cpu;
    for_each_domain(this_cpu, sd) {
        unsigned int imbalance;
        imbalance = sd->imbalance_pct + (sd->imbalance_pct - 100) / 2;
        if ((sd->flags & SD_WAKE_AFFINE) &&
                !task_hot(p, rq->timestamp_last_tick, sd)) {
            if (cpu_isset(cpu, sd->span)) {
                schedstat_inc(sd, ttwu_move_affine);
                goto out_set_cpu;
            }
        } else if ((sd->flags & SD_WAKE_BALANCE) &&
                imbalance*this_load span)) {
                schedstat_inc(sd, ttwu_move_balance);
                goto out_set_cpu;
            }
        }
    }
    new_cpu = cpu;
out_set_cpu:
    new_cpu = wake_idle(new_cpu, p);
    if (new_cpu != cpu) {
        set_task_cpu(p, new_cpu);
        task_rq_unlock(rq, &flags);
        rq = task_rq_lock(p, &flags);
        old_state = p->state;
        if (!(old_state & state))
            goto out;
        if (p->array)
            goto out_running;
        this_cpu = smp_processor_id();
        cpu = task_cpu(p);
    }
out_activate:
#endif
--------------------------------------------------------------------------------
5.If the process is in the TASK_UNINTERRUPTIBLE state, it decreases the nr_uninterruptible field of the target runqueue, and sets the p->activated field of the process descriptor to -1.
|----------------------------------------------|
|   if (old_state == TASK_UNINTERRUPTIBLE) {   |
|       rq->nr_uninterruptible--;              |
|       p->activated = -1;                     |
|   }                                          |
|----------------------------------------------|
6.更新唤醒进程p的平均睡眠时间sleep_avg和动态优先级prio;记录该进程唤醒前的睡眠状态;将该进程插入活跃优先级数组
|----------------------------------------------|
|   activate_task(p, rq, cpu == this_cpu);     |
|----------------------------------------------|
7. 如果唤醒进程p的动态优先级prio比当前进程current的动态优先级高则当前进程的TIF_NEED_RESCHED就需要设置
If either the target CPU is not the local CPU or if the sync flag is not set, it checks whether the new runnable process has a dynamic priority higher than that of the current process of the rq runqueue (p->prio curr->prio); if so, invokes resched_task( ) to preempt rq->curr.
|----------------------------------------------|
|   if (!sync || cpu != this_cpu) {            |
|       if (TASK_PREEMPTS_CURR(p, rq))         |
|           resched_task(rq->curr);            |
|   }                                          |
|   success = 1;                               |
|----------------------------------------------|
8. Sets the p->state field of the process to TASK_RUNNING.
|---------------------------------|
|out_running:                     |
|    p->state = TASK_RUNNING;     |
|---------------------------------|
9. Invokes task_rq_unlock( ) to unlock the rq runqueue and reenable the local interrupts.
|---------------------------------|
|out:                             |
|    task_rq_unlock(rq, &flags);  |
|---------------------------------|
    return success;
}
本文来自CSDN博客,转载请标明出处:
http://blog.csdn.net/linux__kernel/archive/2007/01/08/1476795.aspx


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/96656/showart_2033781.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP