阻止除一个线程外的所有线程的最佳方法是什么?

时间:2020-01-06 11:17:45

标签: multithreading keil rtos cmsis

我正在一个项目上,当某个线程开始执行时,我需要阻塞所有线程。我考虑过使用线程标志,但是我相信这将涉及对所有线程添加检查。我还考虑过使用互斥锁来阻塞所有关键线程,但关键线程除外,我需要执行/拥有对处理器的唯一控制权。之所以没有使用互斥锁,是因为我已经读到它仅与资源有关,并且如果某些线程未链接到互斥锁,它们仍然会继续执行,但是我可能对此有误解。

能否请您告诉我我对互斥锁想法的方法是否正确或是否应该使用另一种方法?

编辑:我正在STM32H753芯片上使用Keil RTX 5 / CMSIS RTOS 2

谢谢

3 个答案:

答案 0 :(得分:3)

CMSIS RTOS具有一对功能osKernelLock()osKernelUnlock()-动态修改线程优先级或使用互斥锁是不必要的,并且可能不明智。

其他任何实时操作系统都将具有类似的关键部分 API。

请注意,这仅防止任务上下文切换;它不会阻止中断运行。通常这是理想的,但是如果要防止这种情况,可以使用_disable_irq()/_enable_irq()来禁用所有中断。这样可以防止任务切换的中断。

禁用中断是蛮力的,即使调度程序锁定,它也会对系统的实时行为产生更大的影响。通常,它只应在很短的时间内完成(调度程序应该锁定)。

答案 1 :(得分:0)

您正在使用什么RTOS?我假设您使用的是基于优先级的RTOS。

不要使用线程标志或互斥体来分层另一种调度机制。只需使用已有的调度程序即可。

如果您希望一个线程专门运行,则将该线程设置为最高优先级线程。 RTOS调度程序将运行可运行的最高优先级线程。如果您的线程具有最高优先级并且不会阻塞自身,则其他线程将不会运行。在CMSIS-RTOS中,您可以使用osThreadSetPriority()更改线程的优先级。

答案 2 :(得分:0)

请勿直接从用户代码中更改任务的优先级。大多数RTOS提供使我们能够做到这一点的API,但这是不好的样式,因为它产生了超出其解决范围的更多问题。一个例外是某些RTOS在内部对此起作用(例如,具有优先级继承的互斥锁以避免某些多任务问题)。

我猜想您只想在系统加电阶段或运行时的另一个非常特殊的阶段使用更长的关键部分。否则,您应该真正听@Clifford的评论,并询问您的优先级分配和任务分解

如果仅在初始化/加电阶段需要该连续时间,则这也是典型的情况,如果设计良好的任务也可能出现这种情况。在这种情况下,您需要的是运行级别管理

运行级别管理

最简单的实现方法是使用两个计数信号灯资源在RTOS之上编写一个小库: 一个用于当前的运行级别,另一个用于下一个运行级别。 输入运行级别后,信号量将填充与必须在运行级别管理控制下的任务一样多的令牌。 每个等待处理给定运行级别的任务都试图从 current-runlevel 信号量获取其令牌。 任务完成其运行级别部分后,它将访问下一级信号量,该信号量此时将不可用。

在填充运行级别管理配置之前,您可以自己绘制一个 sequence diagram 要检查在哪一点,任务无论出于何种原因都必须等待其他任务。 通常,对于每个任务,只有几个运行级别是相关的-每个运行级别,相关任务的集合也可能很小。 因此,您可能需要添加一个WaitForRunlevelNumber(N)之类的辅助功能,并使用一个循环来自动处理那些不相关的运行级别。

如果所有需要显式同步的阶段均已完成,则运行级管理必须完成。 然后,所有任务被释放为自由。 有时,如果低优先级任务已完成所有关键阶段,则希望它们早些发布。 然后,维护的任务数可能会从一个运行级别减少到下一个运行级别。

相关问题