RT throttlingvue activated用法问题求助大神

linux-kernel mailing list
Peter Zijlstra wrote:
> On Fri, Aug 23, 2013 at 10:53:02AM +0200, Martin Mokrejs wrote:匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。Access denied | lkml.org used Cloudflare to restrict access
Please enable cookies.
What happened?
The owner of this website (lkml.org) has banned your access based on your browser's signature (3a4dba59630d6bce-ua98).Linux上调度策略为SCHED_FIFO的实时进程是根据优先级抢占运行的。当没有更高优先级的实时进程抢占,而此进程又由于bug等原因长时间运行,不调度其它进程,系统就会出现无响应。这里要分析的RT
throttling就是针对此种情况的,它通过限制每个单位时间内分配给实时进程的CPU运行时间,来防止上述情况的出现。
标准的设置是1s的时间内,实时进程的运行时间是950ms,其余的50ms时间给normal进程使用。
sched_rt_period_us值为1000000us=1s,表示单位时间为1s
sched_rt_runtime_us值为950000us=0.95s,表示实时进程的运行时间为0.95s。
这两个接口的实现代码如下:
Kernel/sysctl.c的kern_table片段
& & .procname = &sched_rt_period_us&,
& & .data&&
= &sysctl_sched_rt_period,
& & .maxlen&&
= sizeof(unsigned int),
& & .mode&&
& & .proc_handler = sched_rt_handler,
& & .procname = &sched_rt_runtime_us&,
& & .data&&
= &sysctl_sched_rt_runtime, & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&
& & .maxlen&&
= sizeof(int),
& & .mode&&
& & .proc_handler = sched_rt_handler,
sched_rt_period_us接口设置的是sysctl_sched_rt_period变量,sched_rt_runtime_us接口设置的是sysctl_sched_rt_runtime变量。读写的实现都是通过sched_rt_handler函数,这里就不具体分析了。
我们知道了如何设置RT throttling,那么它是如何工作的呢?在实时进程的运行时间超出设定的阈值是如何处理的?
static void update_curr_rt(struct&rq&*rq)
& &&if&(curr-&sched_class != &
rt_sched_class)
&/*判断当前进程调度类*/
&& & & &return;
& &&/*运行队列现在的时间与当前进程开始运行时间之差*&*/
& &&delta_exec
= rq_clock_task(rq)
- &curr-&se.exec_start
& &&curr-&se.sum_exec_runtime += &delta_exec; &/*更新进程的真实运行时间*/
& & & & & & & & & & & & & & & & & & & & & & & & & &&
& &&curr-&se.exec_start = &rq_clock_task(rq);
rt_bandwidth_enabled())&&/*判断RT throttling是否开启*/
&& & & &return;
& &&for_each_sched_rt_entity(rt_se) {
&/*/*遍历此实时进程的调度单元*/*/
& & & &&struct&rt_rq
rt_rq_of_se(rt_se);
& & & &&if&(sched_rt_runtime(rt_rq)
!= &RUNTIME_INF)&{
& & & & & &&rt_rq-&rt_time += &delta_exec;
& & & & & & /*rt_rq的运行时间是否超过了分配给它的时间片*/ &&
& & & & & &&if&(sched_rt_runtime_exceeded(rt_rq))
& & & & & & & &&resched_task(curr);
& & & & & &&} &
& & & &&} &
update_curr_rt函数用来更新当前实时进程的运行时间统计值,如果当前进程不是实时进程,即调度类不为rt_sched_class,则直接返回。
delta_exec值为此运行队列的当前时间与此进程开始运行时间之差,也即是此进程此次调度运行的时长。然后更新进程的真实运行时间和开始运行时间。
rt_bandwidth_enabled函数判断sysctl_sched_rt_runtime变量值是否大于0,如果此变量值设置为RUNTIME_INF(很大的负数),就关掉了RT
throttling功能,这里就会直接返回。
然后遍历此实时进程的调度实体,找到相应的就绪队列,更新运行时间后,通过sched_rt_runtime_exceeded函数判断是否此实时进程是否超过了分配给它的时间片。
sched_rt_runtime_exceeded代码片段:
& & u64 runtime&=
sched_rt_runtime(rt_rq);&&&/*获取当前队列的最大运行时间*/&&
& & & & & & & & & & & & & & & & & & & & & & & &
& & if&(rt_rq-&rt_throttled
) &&&/*当前队列的实时调度受到限制*/&&&&
&& & & &return&rt_rq_throttled(rt_rq);
& &&/*当前队列的最大运行时间大于当前队列的调度周期时间*/
& &&if&(runtime
&= sched_rt_period(rt_rq))&&
&& & & &return&0;
& &&balance_runtime(rt_rq);
&& &runtime
= sched_rt_runtime(rt_rq);
&&/*重新获取当前队列的最大运行时间*/
&& &if&(runtime
== RUNTIME_INF)
&/*关闭了RT throttling*/
&& & & &return&0;
runtime值为当前队列的最大运行时间rt_runtime。rt_throttled字段表示当前队列的实时调度是否受到限制,如果受到限制了,就直接返回1,在update_curr_rt函数中就会调用resched_task函数执行进程切换,让出cpu。
如果当前队列的最大运行时间大于当前队列的调度周期时间,则返回0,这样此运行队列上的任务还能够继续运行。
balance_runtime函数在RT_RUNTIME_SHARE特性使能的情况下,如果当前队列的运行时间超过了最大运行时间,则可以从其他cpu上借用时间。具体代码这里先不分析,后面分析。
重新获取当前队列的最大运行时间runtime,如果值等于RUNTIME_INF说明关闭了RT
throttling,则直接返回0。
sched_rt_runtime_exceeded代码片段:
& &&if&(rt_rq-&rt_time & &runtime)
{ &/*累计运行时间大于最大运行时间*/ & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & &&
&& & & &struct&rt_bandwidth *rt_b&=
sched_rt_bandwidth(rt_rq);
& & & &&if&(likely(rt_b-&rt_runtime
& & & & & &&rt_rq-&rt_throttled = &1;
& & & & & &&printk_deferred_once(&sched: RT throttling activated\n&);
& & & & } else&{
& & & & & &&rt_rq-&rt_time = &0;
& & & &&} &
& & & &&if&(rt_rq_throttled(rt_rq))&{
&/*检查队列的实时调度是否受到限制*/
& & & & & &&sched_rt_rq_dequeue(rt_rq);
&/*将调度实体从实时运行队列中删除*/
& & & & & &&return&1;
& & & &&} &
如果累计运行时间大于最大运行时间,就会执行上面的代码片段。rt_b为运行队列rt_rq的进程组带宽控制结构体指针,如果rt_runtime即此进程组的任务运行时间额度值有效,则设置rt_throttled为1,表明此队列的实时调度受到限制,并打印出“sched:
RT throttling activated”信息。接着检查队列的实时调度如果受到限制,则返回1,在update_curr_rt函数中让出cpu。
在前面讲到balance_runtime在当前队列运行时间超过最大运行时间后,可以从其他cpu上借用时间,下面具体分析代码看下是如何实现的。
static int balance_runtime(struct&rt_rq&*rt_rq)
sched_feat(RT_RUNTIME_SHARE))&&&/*RT_RUNTIME_SHARE支持多个cpu间的rt_runtime共享*/
& & & & & & & & & &&
& & & &&return&more;
& &&if&(rt_rq-&rt_time & &rt_rq-&rt_runtime
& & & &&raw_spin_unlock(&rt_rq-&rt_runtime_lock
& & & &&more =
do_balance_runtime(rt_rq);
& & & &&raw_spin_lock(&rt_rq-&rt_runtime_lock
RT_RUNTIME_SHARE默认是使能的(见kernel/sched/features.h文件)
SCHED_FEAT(RT_RUNTIME_SHARE, true)
它表示支持多个cpu间的rt_runtime共享。如果不支持的话,就直接返回。
如果当前队列的累计运行时间大于最大运行时间,则调用do_balance_runtime函数。
do_balance_runtime函数代码:
& & struct&rt_bandwidth *rt_b&=
sched_rt_bandwidth(rt_rq);
& & struct&root_domain *rd&=
rq_of_rt_rq(rt_rq)-&rd
& &&weight
= cpumask_weight(rd-&span
& & rt_period =
ktime_to_ns(rt_b-&rt_period
); &/*任务组一个控制周期的时间*/ & & & & & & & & & & & & & & & & & & & & & &
& & & & & & & & & & & & &
& & for_each_cpu(i,
&& & & &/*找到在另一个cpu上运行的同一任务组的运行队列*/
&& & & &struct&rt_rq&*iter&=
sched_rt_period_rt_rq(rt_b,
&& & & &if&(iter
&/*同一运行队列则跳过*/
& & & & & &&continue;
& & & &&if&(iter-&rt_runtime == &RUNTIME_INF)
&/*RT throttling关闭,不允许借用时间*/
& & & & & &&goto&
& & & &&diff =
iter-&rt_runtime -
iter-&rt_time
; &/*最大能够借用时间*/
& & & &&if&(diff
& & & & & &&diff =
div_u64((u64)diff,
& & & & & &&if&(rt_rq-&rt_runtime + &diff
& rt_period)
& & & & & & & &&diff =
rt_period - &rt_rq-&rt_runtime
; &/*修正后可借用*/
& & & & & & iter-&rt_runtime -=
& & & & & & rt_rq-&rt_runtime +=
& & & & & &&more =
& & & & & &&if&(rt_rq-&rt_runtime ==
rt_period) {
/*满足条件退出,否则继续从其他cpu借用*/
& & & & & & & &&break;
& & & &&} &
rd-&span表示此调度域的rq可运行的cpu的一个mask,这里会遍历此mask上的cpu,如果对应的cpu的rq和当前的rq是同一运行队列,则直接跳过;如果对应的cpu的rq已关闭RT
throttling功能,则不允许借用时间。内核中关于这块代码的注释是:
Either all rqs have inf runtime and there's nothing to steal or __disable_runtime() below sets a specific rq to inf to indicate its been disabled and disalow stealing.
大概意思是如果所有的运行队列都设置为RUNTIME_INF即关闭了RT throttling功能,则没有时间可以借用。或者某个指定的运行队列调用__disable_runtime()函数,则不允许别的借用自己的时间。
diff是iter运行队列最大能够借用的时间,后面经过修正后,将diff加入到rt_rq的最大可运行时间上。如果新的最大可运行时间等于此任务组的控制周期的时间,则不需要接着再从其他的CPU上借用时间,就直接break退出。
实时进程所在的cpu占用超时,可以向其他的CPU借用,将其他CPU的时间借用过来,这样此实时进程所在的CPU占有率达到100%,这样做的目的是为了避免实时进程由于缺少CPU时间而向其他的CPU迁移,减少不必要的迁移成本。此cpu上为绑定核的普通进程可以迁移到其他cpu上,这样就会得到调度。但是如果此CPU上有进程绑定核了,那么就只有在这里饿死了。
本文已收录于以下专栏:
相关文章推荐
以下是本人分析的内核新的调度类SCHED_DEADLINE调度类,这个调度类没有进主线之前叫EDF(Earliest DeadlineFirst)。在3.14的内核时进入了主线。本文是基于没有进主线之...
LWIP的IP层数据处理代码解析
继续分析rt-thread的网络接收数据部分的代码。。。。
上移章节我们介绍了数据如何从网卡接收到lwip的pbuf里面的,现在我们紧跟着上一章节的内容介绍下网络数据...
人生苦短,都说必须python,那么我分享下我是如何从小白成为Python资深开发者的吧。2014年我大学刚毕业..
node routines for finsh shell.
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
Variable implementation in finsh shell.
* COPYRIGHT (C) 2006 - 2013, RT-Thread Developmen...
这一期来了解一下Ralink的RT3052芯片,也许在做产品开发的人会不屑于这么陈旧的芯片,但是当你了解了MT7688或者MT7621之后就会发现,这些芯片的核心思想和开发方式都是不变的,差别就是各项...
编写本文稿的目的,在于通过分析stm32平台上的串口中断源码,学习
RTT中如何编写中断处理程序
如何编写RTT设备驱动接口代码
了解串行设备的常见处理机制
先以RTT...
error number for finsh shell.
* COPYRIGHT (C) 2013, Shanghai Real-Thread Technology Co., ...
Variable implementation in finsh shell.
* COPYRIGHT (C) 2006 - 2013, RT-Thread Developmen...
token lex for finsh shell.
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
* This function will change the previously allocated memory block.
* @param rmem pointer to...
他的最新文章
讲师:汪剑
讲师:陈守元
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 code activated 的文章

 

随机推荐