关键词:互斥量问题,互斥量锁死
rt_mutex_t step_data_mutex = RT_NULL; /* 指向互斥量的指针 */
RTOS:rt thread 3.1.5
1.线程A优先级低,以20ms的周期循环执行。
2.线程B优先级高,通讯服务线程,接收到命令时可能连续执行命令解析工作。
3.A\B 线程共同使用一组变量,所以使用互斥量管理变量的使用,保证同一时间只能一个线程使用。
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线程长期占有
A 线程获取到互斥量后,调用 rt_enter_critical(); /调度器上锁/
A 线程执行完后 释放互斥量,再调用 rt_exit_critical(); /调度器解锁/
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