更新平均睡眠时间和动态优先级 -- recalc_task_prio( )

  • schedule()片段

进程next被唤醒后(唤醒前处于TASK_INTERRUPTIBLE状态),现在已经被schedule()选中即将投入运行,在得到CPU控制权之前需要重新计算其sleep_avg和prio:
     if  ( ! rt_task(next)  &&  next -> activated  >   0 {
        unsigned 
long long delta = now - next->timestamp;     //(1)
        if (unlikely((long long)(now - next->timestamp) < 0)) //(2)
            delta = 0;
        
if (next->activated == 1)
            delta 
= delta * (ON_RUNQUEUE_WEIGHT * 128 / 100/ 128;

        array 
= next->array;
        dequeue_task(next, array);                        
//(3)
        recalc_task_prio(next, next->timestamp + delta);  //(4)
        enqueue_task(next, array);                        //(5)
    }
//(1)
        next->timestamp               now
--------------+                        +-------------
 running      |                        |
              |                        |
              |       sleeping         |
              +------------------------+

//(2) 计算delta
//(3) 进程next退出活跃队列
//(4) 重新计算平均睡眠时间和动态优先级
//(5) 根据新计算的动态优先级将进程next重新插入活跃队列


  • recalc_task_prio( )
更新进程p的sleep_avg和prio
    The recalc_task_prio( ) function updates the average sleep time and the dynamic priority of a process. It receives as its parameters a process descriptor pointer p and a timestamp now computed by the sched_clock( ) function.

static void recalc_task_prio(task_t *p, unsigned long long now)
{
1. 计算本次睡眠时间(sleep_time)
|-------------------------------------------------------------|
|   /* Caller must always ensure 'now >= p->timestamp' */     |
|   unsigned long long __sleep_time = now - p->timestamp;     |
|   unsigned long sleep_time;                                 |
|                                                             |
|   if (__sleep_time > NS_MAX_SLEEP_AVG)                      |
|       sleep_time = NS_MAX_SLEEP_AVG;                        |
|   else                                                      |
|       sleep_time = (unsigned long)__sleep_time;             |
|-------------------------------------------------------------|

2. 如果sleep_time不大于0(没有睡眠),就不用更新进程的平均睡眠时间,直接进入第8步
|----------------------------------|
|   if (likely(sleep_time > 0)) {  |
|----------------------------------|

3. 如果该进程不是内核线程;唤醒前不处于TASK_UNINTERRUPTIBLE状态;其连续睡眠时间超过给定的睡眠时间极限;则该进程的sleep_avg = 1000 - 100 = 900ms
Checks whether the process is not a kernel thread, whether it is awakening from the TASK_UNINTERRUPTIBLE state (p->activated field equal to -1), and whether it has been continuously asleep beyond a given sleep time threshold.
|----------------------------------------------------------------|
|       if (p->mm && p->activated != -1 &&                       |
|           sleep_time > INTERACTIVE_SLEEP(p)) {                 |
|               p->sleep_avg =                                   |
|                   JIFFIES_TO_NS(MAX_SLEEP_AVG - DEF_TIMESLICE);|
|----------------------------------------------------------------|
       } else {

4. 根据当前bonus倍增本次连续睡眠时间sleep_time
执行CURRENT_BONUS宏计算进程 " 原来的平均睡眠时间 "(更新前的平均睡眠时间)所对应的bonus值。如果(10 - bonus)大于 0,函数用这个值与sleep_time相乘(放大本次 连续睡眠时间sleep_time)。 因为要把sleep_time加到进程的平均睡眠时间上, 所以当前平均睡眠时间越短(sleep_avg对应的bonus值越小), sleep_time增加的倍数就越多。
|----------------------------------------------------------------|
|           sleep_time *= (MAX_BONUS - CURRENT_BONUS(p)) ? : 1;  |
|----------------------------------------------------------------|

5. 如果进程p唤醒前处于TASK_UNINTERRUPTIBLE状态;不是内核线程;
a. 如果更新前的平均睡眠时间已经超过了
给定的睡眠时间极限,那么将没有必要更新平均睡眠时间了(就算加上本次连续睡眠时间sleep_time也没有意义),所以将sleep_time置为0,直接进入第6步
b. 如果
更新前的平均睡眠时间加上本次连续睡眠时间超过了 给定的睡眠时间极限,那么就把p->sleep_avg字段置为睡眠 极限 时间并把sleep_avg设置为 0
|------------------------------------------------------------|
|           if (p->activated == -1 && p->mm) {               |
|               if (p->sleep_avg >= INTERACTIVE_SLEEP(p))    |
|                   sleep_time = 0;                          |
|               else if (p->sleep_avg + sleep_time >=        |
|                       INTERACTIVE_SLEEP(p)) {              |
|                   p->sleep_avg = INTERACTIVE_SLEEP(p);     |
|                   sleep_time = 0;                          |
|               }                                            |
|           }                                                |
|------------------------------------------------------------|

6. 把本次连续睡眠时间(sleep_time)加到进程 更新前的 平均睡眠时间上(p->sleep_avg)
|-----------------------------------------|
|           p->sleep_avg += sleep_time;   |
|-----------------------------------------|

7. 检查更新后的平均睡眠时间(p->sleep_avg)是否超过1000个时钟节拍(以纳秒为单位),如果是,函数就把它减到1000个时钟节拍(以纳秒为单位)
|------------------------------------------------|
|           if (p->sleep_avg > NS_MAX_SLEEP_AVG) |
|               p->sleep_avg = NS_MAX_SLEEP_AVG; |
|------------------------------------------------|
        }
    }

8. 根据新的平均睡眠时间sleep_avg更新动态优先级prio
|---------------------------------|
|   p->prio = effective_prio(p);  |
|---------------------------------|
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值