快乐虾
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_FIFO与SCHED_RR两种策略,而对于非实时任务则使用SCHED_NORMAL和SCHED_BATCH两种策略。
1.2 static_prio到load_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_SCALE和TIME_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。