请考虑以下代码:
/*----------------------------------------------------------------------------
First Thread
*---------------------------------------------------------------------------*/
void Thread1 (void const *argument)
{
for (;;)
{
osMutexWait(mutex, osWaitForever);
Thread1_Functions;
osMutexRelease(mutex);
}
}
/*----------------------------------------------------------------------------
Second Thread
*---------------------------------------------------------------------------*/
void Thread2 (void const *argument)
{
for(;;)
{
osMutexWait(mutex, osWaitForever);
Thread2_Functions;
osMutexRelease(mutex);
}
}
据我RTOS's scheduling
注意到,RTOS为每个任务分配了一个特定时间,在此时间结束后,它切换到另一个任务。
然后在这个特定的时间内,在任务的无限循环中,可能循环重复几次,直到任务的特定时间结束
假设任务在少于其时间的一半时间内完成,那么它有时间再次完全运行此任务。
在释放互斥锁之后的最后一行,然后它会比task2第二次实现互斥,我是真的吗?
假设当MCU第二次运行Thread1_Functions
时会发生计时器滴答,然后task2无法运行,因为task1拥有互斥,RTOS再次运行任务1,并且每次Thread1_Functions
都发生计时器滴答,则task2没有跑步的机会,我是真的吗?
答案 0 :(得分:2)
首先,让我清理你描述的调度方法。你说,“RTOS为每个任务分配一个特定的时间,在这段时间结束后,它会切换到另一个任务。”这种调度方法通常称为“时间分片”。并且所有RTOS都不一定总是使用这种方法。时间分片可用于具有相同优先级的任务(或者如果RTOS不支持任务优先级)。但是如果任务具有不同的优先级,那么调度程序将不会使用时间切片,而是根据任务优先级进行调度。
但是我们假设您的示例中的两个任务具有相同的优先级,并且调度程序是时间切片。
释放互斥锁时,调度程序应切换到等待互斥锁的任何更高优先级的任务。但由于Thread2具有相同的优先级,让我们假设调度程序没有切换,并且Thread1继续在其时间片内运行。
在您的场景中,Thread1再次成功获取互斥锁,这可能导致Thread2永远无法运行。为了防止这种情况发生,互斥服务应优先考虑互斥锁的请求。来自较高优先级任务的互斥锁请求获得较高优先级。来自同等优先级任务的互斥锁请求应该先到先得。换句话说,互斥服务应该将来自相同优先级任务的请求放入队列中。请记住,Thread2已经有一个挂起的挂起请求(上面的步骤3)。因此,当Thread1再次尝试获取互斥锁时(步骤6),Thread1的请求应排在Thread2的早期请求之后。当Thread1的第二个互斥锁请求在Thread2的请求后面排队时,调度程序应该阻塞Thread1并切换到Thread2,将互斥锁提供给Thread2。
更新:上面只是一个关于未指定的RTOS如何处理这种情况的想法,以避免使Thread2挨饿。在下面的评论之前,您没有提到具体的RTOS。我不知道Keil RTX是否像我上面描述的那样工作。现在我想知道你的问题到底是什么。
您是否在询问Keil RTX在这种情况下会做些什么?我不确定。您必须查看osMutexRelease()的代码,以查看它是否切换到具有相同优先级的任务。另请参阅osMutexWait()以了解它如何优先考虑具有相同优先级的任务。
或者您是否说明Keil RTX允许Thread2在这种情况下挨饿,您是否在询问如何修复它。要解决这种情况,可以在释放互斥锁后调用osThreadYeild()。像这样:
void Thread1 (void const *argument)
{
for (;;)
{
osMutexWait(mutex, osWaitForever);
Thread1_Functions;
osMutexRelease(mutex);
osThreadYeild();
}
}