RT-Thread: 互斥量问题,互斥量锁死问题调试笔记

关键词:互斥量问题,互斥量锁死

1.rt thread 3.1.5 互斥量问题


rt_mutex_t step_data_mutex = RT_NULL; /* 指向互斥量的指针 */

1.调试环境:


RTOS:rt thread 3.1.5
1.线程A优先级低,以20ms的周期循环执行。
2.线程B优先级高,通讯服务线程,接收到命令时可能连续执行命令解析工作。
3.A\B 线程共同使用一组变量,所以使用互斥量管理变量的使用,保证同一时间只能一个线程使用。


2.问题现象:


1.两个优先级不同的线程获取一个互斥量,在运行一段时间后20分钟左右,导致互斥量释放和获取失败,从而A线程无法再获取到互斥量。
2.根据调试,发现在出现A线程互斥量获取异常前,通常发生过的流程是:
-> A线程获取到互斥量,且未释放
-> 调度到B线程,B线程获取互斥量失败但 返回值为 RT_EOK
-> B 线程 根据 RT_EOK 释放 互斥量,
-> 调度回A线程,A线程释放互斥量后 ,hold = 1,不为0
-> B 线程获取互斥量,houd = 2
-> B 线程 根据 RT_EOK 释放 互斥量,释放互斥量后 ,hold = 1
-> A线程,无法再获取互斥量,互斥量被B线程长期占有

3.临时解决办法:

A 线程获取到互斥量后,调用 rt_enter_critical(); /调度器上锁/

A 线程执行完后 释放互斥量,再调用 rt_exit_critical(); /调度器解锁/

4.问题提示:

1.由于B线程中使用了调度器上锁,所以B线程在获取互斥量时,原本有500ms的等待延时,由于禁止了调度所以延时失效,rt_mutex_take()直接返回。
 

//A 线程结构:优先级4
thread_A()
{
rt_err_t mutex_step_ret;
while(1)
{
mutex_step_ret = rt_mutex_take(step_data_mutex, 500); //获取互斥量
    /*
    应用代码
    */

    if (mutex_step_ret == RT_EOK)
    {
       rt_mutex_release(step_data_mutex); //释放互斥量
    }
    rt_thread_mdelay(20);
}

}

//B 线程结构:优先级3

thread_B()
{
rt_err_t mutex_step_ret;
rt_err_t uwRet = RT_EOK;
while(1)
{
uwRet = rt_mq_recv (can_mq, &g_rx_frame, CAN_MQ_SIZE, 200); /* 获取通讯数据消息 */
    if (RT_EOK == uwRet)
    {
        rt_enter_critical();        /*调度器上锁*/
        mutex_step_ret = rt_mutex_take(step_data_mutex, 500); //获取互斥量

        /*
        应用代码
        */

        if (mutex_step_ret == RT_EOK)
        {
           rt_mutex_release(step_data_mutex); //释放互斥量
        }

        rt_exit_critical();         /*调度器解锁*/
    }
}

}

调试打印信息:

//A/B 线程获取互斥量前后打印信息
//A线程正常运行
work_step_thread_entry(546): sys time = 74633 , ch = 7 , take_thread_name = Hô,hold = 0,value = 1,mutex_step_ret = 0
work_step_thread_entry(549): sys time = 74633 , ch = 7 , take_thread_name = work_step_thread,hold = 1,value = 0,mutex_step_ret = 0
work_step_thread_entry(799): sys time = 74633 , ch = 7 , take_thread_name = Hô,hold = 0,value = 1,mutex_step_ret = 0
//A线程正常运行
work_step_thread_entry(546): sys time = 74673 , ch = 0 , take_thread_name = Hô,hold = 0,value = 1,mutex_step_ret = 0
work_step_thread_entry(549): sys time = 74673 , ch = 0 , take_thread_name = work_step_thread,hold = 1,value = 0,mutex_step_ret = 0
work_step_thread_entry(799): sys time = 74673 , ch = 0 , take_thread_name = Hô,hold = 0,value = 1,mutex_step_ret = 0
//A线程获取互斥量前,打印互斥量信息
work_step_thread_entry(546): sys time = 74693 , ch = 1 , take_thread_name = Hô,hold = 0,value = 1,mutex_step_ret = 0
//A线程获取到互斥量,打印互斥量信息,打印未完成,调度到 B 线程
work_step_thread_entry(549): sys time = 74693 , ch = 1 , take_thread_name = work_step_thread,hold = 1,value = 0,mutex_step_ret =
//B线程获取互斥量前,打印互斥量信息,显示互斥量的持有线程为 A ,take_thread_name = work_step_thread
reply_chs_config_opt_mode(1018):   mutex_take_count = 61 , sys time = 74693 , ch = 4 , take_thread_name = work_step_thread,hold = 1,value = 0 , mutex_step_ret = 74641
//B线程获取互斥量后显示持有线程任然为A,但是返回值为 0
reply_chs_config_opt_mode(1025):   mutex_take_count = 62 , sys time = 74694 , ch = 4 , take_thread_name = work_step_thread,hold = 1,value = 0 , mutex_step_ret = 0
//B线程释放互斥量前,互斥量信息打印
reply_chs_config_opt_mode(1632):mutex_release_count = 61 , sys time = 74694 , ch = 4 , take_thread_name = work_step_thread,hold = 1,value = 0, mutex_step_ret = 0
//B线程释放互斥量后,互斥量信息打印
reply_chs_config_opt_mode(1635):mutex_release_count = 61 , sys time = 74694 , ch = 4 , take_thread_name = work_step_thread,hold = 1,value = 0, mutex_step_ret = 0
//B线程释放互斥量后,hold 检查报警打印,正常释放后 hold 应该为 0 ,显示释放失败。
reply_chs_config_opt_mode(1639):step_data_mutex.hold = 1,value = 0,step_data_mutex.hold error , mutex_step_ret = 0
//调度回A线程,继续打印未完成内容
0
//A线程,打印信息
work_step_74695 , ch = 1 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = 0
//A线程获取互斥量前,打印互斥量信息
work_step_thread_entry(546): sys time = 74716 , ch = 2 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = 0
//B线程释放互斥量前,互斥量信息打印
reply_chs_config_opt_mode(1018):   mutex_take_count = 62 , sys time = 74772 , ch = 5 , take_thread_name = can3,hold = 1,value = 0 , mutex_step_ret = 74720
//B线程释放互斥量后,互斥量信息打印
reply_chs_config_opt_mode(1025):   mutex_take_count = 63 , sys time = 74773 , ch = 5 , take_thread_name = can3,hold = 2,value = 0 , mutex_step_ret = 0
//B线程释放互斥量前,互斥量信息打印
reply_chs_config_opt_mode(1632):mutex_release_count = 62 , sys time = 74773 , ch = 5 , take_thread_name = can3,hold = 2,value = 0, mutex_step_ret = 0
//B线程释放互斥量后,互斥量信息打印
reply_chs_config_opt_mode(1635):mutex_release_count = 62 , sys time = 74773 , ch = 5 , take_thread_name = can3,hold = 1,value = 0, mutex_step_ret = 0
//B线程释放互斥量后,hold 检查报警打印,正常释放后 hold 应该为 0 ,显示释放失败。
reply_chs_config_opt_mode(1639):step_data_mutex.hold = 1,value = 0,step_data_mutex.hold error , mutex_step_ret = 0
//之后A线程就再也无法获取到互斥量,houd 在B线程释放后也不会为0
reply_chs_config_opt_mode(1018):   mutex_take_count = 63 , sys time = 74849 , ch = 6 , take_thread_name = can3,hold = 1,value = 0 , mutex_step_ret = 74798
reply_chs_config_opt_mode(1025):   mutex_take_count = 64 , sys time = 74850 , ch = 6 , take_thread_name = can3,hold = 2,value = 0 , mutex_step_ret = 0
reply_chs_config_opt_mode(1632):mutex_release_count = 63 , sys time = 74850 , ch = 6 , take_thread_name = can3,hold = 2,value = 0, mutex_step_ret = 0
reply_chs_config_opt_mode(1635):mutex_release_count = 63 , sys time = 74850 , ch = 6 , take_thread_name = can3,hold = 1,value = 0, mutex_step_ret = 0
reply_chs_config_opt_mode(1639):step_data_mutex.hold = 1,value = 0,step_data_mutex.hold error , mutex_step_ret = 0
reply_chs_config_opt_mode(1018):   mutex_take_count = 64 , sys time = 74943 , ch = 7 , take_thread_name = can3,hold = 1,value = 0 , mutex_step_ret = 74876
reply_chs_config_opt_mode(1025):   mutex_take_count = 65 , sys time = 74943 , ch = 7 , take_thread_name = can3,hold = 2,value = 0 , mutex_step_ret = 0
reply_chs_config_opt_mode(1632):mutex_release_count = 64 , sys time = 74943 , ch = 7 , take_thread_name = can3,hold = 2,value = 0, mutex_step_ret = 0
reply_chs_config_opt_mode(1635):mutex_release_count = 64 , sys time = 74944 , ch = 7 , take_thread_name = can3,hold = 1,value = 0, mutex_step_ret = 0
reply_chs_config_opt_mode(1639):step_data_mutex.hold = 1,value = 0,step_data_mutex.hold error , mutex_step_ret = 0
work_step_thread_entry(549): sys time = 75216 , ch = 2 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = -2
work_step_thread_entry(804): sys time = 75216 , ch = 2 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = -2
work_step_thread_entry(546): sys time = 75236 , ch = 3 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = -2
work_step_thread_entry(549): sys time = 75736 , ch = 3 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = -2
work_step_thread_entry(804): sys time = 75736 , ch = 3 , take_thread_name = can3,hold = 1,value = 0,mutex_step_ret = -2

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值