唤醒 -- try_to_wake_up()

    唤醒操作通过函数wake_up进行,它会唤醒指定的等待队列上的所有进程。它调用函数try_to_wake_up,该函数负责将进程设置为 TASK_RUNNING状态,调用activate_task将此进程放入可执行队列,如果被唤醒的进程优先级比当前正在运行的进程的优先级高,还有设 置need_resched标志。 通常哪段代码促使等待条件达成,它就负责随后调用wake_up()函数。
    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 && this_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 <= 100*load) {
             if (cpu_isset(cpu, sd->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 < rq->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;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值