前情提要:
在threadX的队列测试中,发现了收取数据的线程总共读取数据的次数会大于另一个发送数据的线程发送的次数,如下所示(thread1 thread2);直觉上这样的情况肯定是有问题的,因此对该问题进行了详细的研究
概括一下整个程序的内容:
——Thread0 优先级最高,每隔10个tick打印其他线程的一些状态
——Thread1 向队列中发送数据,thread2从队列中读取数去
——Thread1 thread2优先级相同,时间片长度一致
线队列的定义如下,其中有一些宏
整体含义为:创建了一个名为 queue 0的队列,队列中允许的数据长度为100条
线程1向队列中不断发送数据,入口函数如下
线程2不断从队列中读取数据,入口函数如下
Debug过程
首先基于两个事实:
—— receive message 一定 <= sent message
—— 线程被挂起有两种可能:1.时间片结束 2.被更高优先级的进程抢占
推断进程是在运行在如下箭头所指位置时从运行态变为ready status 或 suspended status
(消息发送完成 与 thread_1_messages_sent自增之前)
针对以上两种可能进行一一验证
首先,对于时间片结束在箭头所指位置,导致thread_1_messages_sent这个变量没有增加,而已经往队列里发了一条消息;这样的话thread2就可用从队列中读取这条数据,从而让thread2_messages_received大于thread_1_messages_sent
这显然是有可能的
因此在重新加一个全局变量,在收发消息之前就自增1,那不就可以解决问题了吗
重新进行测试,发现仍然存在 thread_2_counter = thread_1_counter +1 的情况,问题仍然存在
继续分析
Thread_1_counter和thread_2_counter都是volatile的全局变量,不存在线程切换导致值出现问题
从ThreadX官方文档中发现
根据以上信息,猜测是消息队列的机制导致该问题出现
在thread0的打印函数中增加队列信息的打印,有了如下发现:每次出现thread_2_counter = thread_1_counter +1的问题时,队列中可用的消息数量都是0
同时观察异常打印的上一条
从数值的变化中可用发现,两条打印之间 thread1发送了一共123624条消息,thread2接受了123684条消息
Thread2比thread1多接收了60条消息,而队列中的消息数,从59变为了0
这引发了新的问题,多出的一条消息从哪来的
查看官方文档中对消息队列的描述,蓝色部分的描述引起了我的注意
查看源码中函数_tx_queue_receive的实现,发现了如下代码实现;当rtos发现队列已满,而且有线程尝试写数据被挂起后,在读完所有队列中的内容,甚至会把那个被挂起的线程想要写的数据也读走,从而就引起了最开始遇到的问题
至此,问题解决