uclinux内核的任务优先级及其load_weight

时间:2022-06-15 08:04:14

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

 

本文适用于

ADSP-BF561

uclinux-2008r1.5-RC3(移植到vdsp5)

Visual DSP++ 5.0(update 5)

 

欢迎转载,但请保留作者信息

 

1.1    任务分类

内核将任务分为两类,一类是实时任务,另一类是非实时任务,这两类任务的优先级并不同,在include/linxu/sched.h中有如下定义:

/*

 * Priority of a process goes from 0..MAX_PRIO-1, valid RT

 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH

 * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority

 * values are inverted: lower p->prio value means higher priority.

 *

 * The MAX_USER_RT_PRIO value allows the actual maximum

 * RT priority to be separate from the value exported to

 * user-space.  This allows kernel threads to set their

 * priority to a value higher than any user task. Note:

 * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.

 */

 

#define MAX_USER_RT_PRIO    100

#define MAX_RT_PRIO         MAX_USER_RT_PRIO

 

#define MAX_PRIO       (MAX_RT_PRIO + 40)

即实时任务的优先级为[0, 99],而非实时任务的优先级则为[100, 139]。这个数值越小,表示其优先级越高。

相应的,调度策略也分为两类:

/*

 * Scheduling policies

 */

#define SCHED_NORMAL        0

#define SCHED_FIFO     1

#define SCHED_RR       2

#define SCHED_BATCH         3

其中对于实时任务可以使用SCHED_FIFOSCHED_RR两种策略,而对于非实时任务则使用SCHED_NORMALSCHED_BATCH两种策略。

1.2    static_prioload_weight的转换

每一个任务都有一个prio成员和load_weight成员,可以从优先级计算load_weight,这个工作由set_load_weight函数完成:

static void set_load_weight(struct task_struct *p)

{

     if (has_rt_policy(p)) {

#ifdef CONFIG_SMP

         if (p == task_rq(p)->migration_thread)

              /*

               * The migration thread does the actual balancing.

               * Giving its load any weight will skew balancing

               * adversely.

               */

              p->load_weight = 0;

         else

#endif

              p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority);

     } else

         p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio);

}

这里有:

#define is_rt_policy(p)     ((p) != SCHED_NORMAL && (p) != SCHED_BATCH)

#define has_rt_policy(p)    unlikely(is_rt_policy((p)->policy))

从这里就可以看出对于实时任务和非实时任务来讲,它们的计算方式是不同的。

#define PRIO_TO_LOAD_WEIGHT(prio) /

     LOAD_WEIGHT(static_prio_timeslice(prio))

#define RTPRIO_TO_LOAD_WEIGHT(rp) /

     (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))

比较这两个宏定义可以发现实时任务计算所得的load_weight值都将大于非实时任务的load_weight值,下面对此原因进行分析:

#define LOAD_WEIGHT(lp) /

     (((lp) * SCHED_LOAD_SCALE) / TIME_SLICE_NICE_ZERO)

#define SCHED_LOAD_SCALE    128UL    /* increase resolution of load */

#define TIME_SLICE_NICE_ZERO DEF_TIMESLICE

#define DEF_TIMESLICE       (100 * HZ / 1000)

由于SCHED_LOAD_SCALETIME_SLICE_NICE_ZERO这两个值均为常数,因而传递给LOAD_WEIGHT的值越大,计算所得的结果也越大。

在上面的宏定义中,使用了static_prio_timeslice函数:

static unsigned int static_prio_timeslice(int static_prio)

{

     if (static_prio < NICE_TO_PRIO(0))

         return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio);

     else

         return SCALE_PRIO(DEF_TIMESLICE, static_prio);

}

#define SCALE_PRIO(x, prio) /

     max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE)

从这里可以看出,传给此函数的static_prio值越小,其计算所得的值越大。

再回头看

#define RTPRIO_TO_LOAD_WEIGHT(rp) /

     (PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO) + LOAD_WEIGHT(rp))

由于非实时任务的值都将大于MAX_RT_PRIO,因此PRIO_TO_LOAD_WEIGHT(MAX_RT_PRIO)计算所得的值都将大于非实时任务计算所得的值,再加上LOAD_WEIGHT(rp)自然更大。从而可以得出结论:

实时任务计算所得的load_weight值都将大于用户任务的load_weight值,且任务的优先级越低,计算所得的值越大,不论它是实时任务还是非实时任务。

对于init_task这个默认的任务来讲,在HZ取默认值250的情况下,其load_weight的值将为128