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

快乐虾

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

[email protected]

本文适用于

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

你可能感兴趣的:(thread,工作,.net,Blog)