嵌入式技术论坛
直播中

杨万富

7年用户 1525经验值
擅长:526774
私信 关注
[经验]

关于RT-Thread硬件定时器的线程安全问题及其解决办法

问题发生的场景和现象:

使用armlink大神的modbus库,在串口中断中会调用rt_timer_start来启动定时器,判断下一个modbus帧是否超时。

在程序运行后有极小的几率会在串口中断中卡死。

问题大致定位的位置

如上文所述,在串口中断USART_IRQHandler中会调用rt_timer_start来启动定时器实现modbus的时序控制,同时也单独启动了一个modbus线程,其中也会执行rt_timer_start来控制modbus的超时。但是在执行rt_timer_start时有极小几率(约1%)会卡死, 卡死位置在timer.c下面这个for循环中:

观察变量可以看到如下结果:定时器链表 rt_timer_list 链表变成了死循环链表:

通过多次断点尝试,发现了如下的调用栈和调用位置:

猜测的原因和解决办法

可以看到在执行rt_timer_start时被打断了,打断后又执行了一遍rt_timer_start,导致的后果的是,执行顺序变成了:

_rt_timer_remove 执行完之后被打断

_rt_timer_remove

rt_list_insert_after

回到被打断的位置,继续往下执行:rt_list_insert_after

第一次remove已经移除了链表节点,第二次remove无效;第三次第四次插入两次,造成链表变成死循环链表。

可能的解决办法

个人认为解决办法在于 timer.c 中:

在324行手动开启了中断,之后又在336行几乎是又立即关闭了中断。所以我个人认为:

324行这里是否不需要开启中断。

或者另一方面来说,rt_timer_start这个函数本身就是线程不安全的?即使这样也希望能做一个断言判断一下,不然这样在死循环里不出来很难排查问题。

原作者:RT-Thread物联网操作系统

更多回帖

发帖
×
20
完善资料,
赚取积分