搜索
bottom↓
回复: 10

对不起,还是那个BUG!

[复制链接]

出0入0汤圆

发表于 2010-5-12 09:50:39 | 显示全部楼层 |阅读模式
这次的标题应该不是太显眼了吧。。。
RTT管理员对我提出的“rt_tick_increase()函数的不妥”似乎不以为然,熟视无睹,都提出来了,还不仔细更正,技术问题岂能如此轻率!?

我再给你分析一遍,rt_tick_increase()函数的调用关系跟踪如下(-> 符号表示调用关系, == 符号表示等同调用关系):
rt_tick_increase() -> rt_timer_check() -> t->timeout_func(t->parameter) == rt_thread_timeout(thread)
-> rt_schedule() -> {rt_current_thread = to_thread;}
到此,rt_current_thread已经被改变了!而当rt_timer_check()函数返回之后,rt_tick_increase()函数会调用
rt_thread_self()来获得当前线程,其实这时候它返回的并不是“被中断的当前线程”,而是rt_thread_timeout()函数引起的某个新的就绪线程。
所以对它进行{-- thread->remaining_tick;}操作是错误的!

如果我有分析不对的,也请版主指出,只是不要封贴!

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2010-5-12 10:10:33 | 显示全部楼层
我斗胆帮楼主改下内容,如果楼主能接受,我想这是一个很好的讨论.


标题: 再次讨论 RTT- 定时器tick的不妥

rt_tick_increase()函数的调用关系跟踪如下(-> 符号表示调用关系, == 符号表示等同调用关系):
rt_tick_increase() -> rt_timer_check() -> t->timeout_func(t->parameter) == rt_thread_timeout(thread)
-> rt_schedule() -> {rt_current_thread = to_thread;}
到此,rt_current_thread已经被改变了!而当rt_timer_check()函数返回之后,rt_tick_increase()函数会调用
rt_thread_self()来获得当前线程,其实这时候它返回的并不是“被中断的当前线程”,而是rt_thread_timeout() 函数引起的某个新的就绪线程。
所以对它进行{-- thread->remaining_tick;}操作是错误的!


另贴一个FFXZ的公开邮件:(我未经FFXZ同意就公开了,图中隐去的是各人的ID,并非有意掩饰什么.)

(原文件名:mail-ffxz.jpg)

出0入0汤圆

发表于 2010-5-12 10:44:30 | 显示全部楼层
回复【楼主位】9509238  
这次的标题应该不是太显眼了吧。。。
rtt管理员对我提出的“rt_tick_increase()函数的不妥”似乎不以为然,熟视无睹,都提出来了,还不仔细更正,技术问题岂能如此轻率!?
我再给你分析一遍,rt_tick_increase()函数的调用关系跟踪如下(-> 符号表示调用关系, == 符号表示等同调用关系):
rt_tick_increase() -> rt_timer_check() -> t->timeout_func(t->parameter) == rt_thread_timeout(thread)
-> rt_schedule() -> {rt_current_thread = to_thread;}
到此,rt_current_thread已经被改变了!而当rt_timer_check()函数返回之后,rt_tick_inc......
-----------------------------------------------------------------------

看来我上次对你说的rt_thread_self()的问题理解有误,抱歉。(毕竟不是每一次看问题都能正确理解的,所以当理解不对时也还请及时指出。当时已经给你回帖了,只是后来你并没针对这个问题继续讨论下去,所以还以为就如我理解的那样,没有问题)

这个问题应该是rt_tick_increase() 和 rt_thread_self()结合起来用时才发生?(即rt_tick_increase()的函数调用过程中调用了rt_thread_self())可以考虑把remain tick放到timer_check前面进行,只是这样依然不能避免问题的出现:rt_tick_increase是在中断中被调用,但Cortex-M3和原来的ARM有很大的不同,支持了中断抢占,也就是说,如果这个地方发生了中断抢占,那么也可能会让新的(还未被运行的)线程提前消耗掉它的一个tick数。

针对这类情况,能否给出个测试代码?这样,当修正了时也能够进行回归测试。

出0入0汤圆

 楼主| 发表于 2010-5-12 11:45:57 | 显示全部楼层
回复【2楼】ffxz
-----------------------------------------------------------------------

这回比较爽快,我们别说废话就行。

把rt_timer_check()放到最后面是可以解决问题的。
你说的中断抢占,是有个优先级前提的,相同优先级的中断永远不会发生抢占,所以tick中断不会抢占tick中断自己。而remaining_tick计数器只会在tick中断中被自减。

出0入0汤圆

发表于 2010-5-12 11:55:13 | 显示全部楼层
回复【3楼】9509238  
回复【2楼】ffxz
-----------------------------------------------------------------------
这回比较爽快,我们别说废话就行。
把rt_timer_check()放到最后面是可以解决问题的。
你说的中断抢占,是有个优先级前提的,相同优先级的中断永远不会发生抢占,所以tick中断不会抢占tick中断自己。而remaining_tick计数器只会在tick中断中被自减。
-----------------------------------------------------------------------

不是说OS Tick中断,而是其他中断,其他中断也有可能触发线程切换。

现在越来越觉得太有必要加入一个类似最高级优先级线程的处理了,OS相关的东西都由这个最高优先级线程去执行。

出0入0汤圆

 楼主| 发表于 2010-5-12 14:34:13 | 显示全部楼层
最高优先级线程的存在,能缓解很多关中断压力。但是势必造成更多的线程切换代价,这需要权衡啊!
其它抢占的中断,虽然能触发线程切换,但没有做事实上的切换动作,因为有rt_interrupt_nest计数器的存在。
不管有没有抢占的中断到来,只要把tick中断的优先级设置为最低就可以避免了。

出0入0汤圆

 楼主| 发表于 2010-5-12 14:40:53 | 显示全部楼层
ffxz说得对,即使tick中断优先级最低,还是会出现同样的问题。
可以说,这就是一个不妥之处,并不是一个bug级别的东西。

出0入0汤圆

发表于 2010-5-12 16:21:11 | 显示全部楼层
使用最高优先级线程的方式应该能够解决这个问题,而线程切换的代价应该还行,只会有实际的事情要处理时才最终切换过去执行。

而且最高优先级线程(或叫做高级中断服务例程)可以把目前的一些线程,例如erx、etx取代,同时也会减少(或完全去掉)系统的关中断时间,提高系统的实时相应能力。

出0入0汤圆

发表于 2010-5-12 16:44:17 | 显示全部楼层
回复【5楼】9509238  
最高优先级线程的存在,能缓解很多关中断压力。但是势必造成更多的线程切换代价,这需要权衡啊!
其它抢占的中断,虽然能触发线程切换,但没有做事实上的切换动作,因为有rt_interrupt_nest计数器的存在。
不管有没有抢占的中断到来,只要把tick中断的优先级设置为最低就可以避免了。
-----------------------------------------------------------------------

rt_interrupt_nest没有用的,执行rt_rescule()函数成功以后rt_current_thread已经变了,当前线程上下文和rt_current_thread变量并不是完全原子操作的,这里面嵌进一些中断是很容易出问题。
还有一个问题就是,在中断可以被抢占的情况下所有内核对象都必须互斥访问,而内核对象是挂在链表上,所以整个链表的读写必须互斥起来,比如我在低优先级的中断里面从某个链表上拆一个对象出来的时候,被高优先级中断打断,然后又去访问这个链表就出问题了。
用最高优先级来做这件事应该是个很好的解决方法,像lwip那样中断不去访问任何一个内核对象,而只把消息打包发给那个线程,线程可以保证执行的原子性和顺序性,代码也可以写得很干净。

btw,9509238,我怎么还是觉得你说话很冲呢?啥叫“别废话就行”啊,你要别人客客气气对你,你自己先客气一点行不?

出0入663汤圆

发表于 2010-5-12 17:11:53 | 显示全部楼层
把rt_current_thread放在真正context switch时再修改?

出0入0汤圆

发表于 2010-5-21 18:02:57 | 显示全部楼层
那个tick溢出的问题基本上已经修正,在把tick变量单位更改为rt_uint8_t测试通过(增加了一个链表,并不需要把每个timer的tick单位更改为64位)。

同时还包括timer_timeout时的一个问题:timer timeout时持有链表有些问题,可能上次拿到的节点已经被超时函数删除。

修正会尽快更新到0.4.x版本上,没问题后再更新到0.3.1版本上。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 17:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表