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

What is the best way to block all threads except one?

我正在做一个项目,我需要在某个线程开始执行时阻塞所有线程。我考虑过使用线程标志,但我相信这会涉及对所有线程添加检查。我还考虑过使用互斥锁来阻止除关键线程之外的所有线程,我需要 execute/have 单独控制处理器。我还没有使用互斥锁的原因是因为我读到它只与资源有关,并且如果某些线程没有链接到互斥锁,它们仍然会继续执行,但是我可能误解了这一点。

你能告诉我我对互斥体的想法是否正确,或者我是否应该使用其他方法?

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

谢谢

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

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

如果您希望一个线程独占运行,则使该线程成为最高优先级线程。 RTOS 调度程序将 运行 准备就绪的最高优先级线程 运行。如果你的线程是最高优先级并且不会阻塞自己,那么其他线程就不会运行。在 CMSIS-RTOS 中,您可以使用 osThreadSetPriority().

更改线程的优先级

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

任何其他 RTOS 都会有类似的临界区 API.

请注意,这只会阻止任务上下文切换;它不会阻止来自 运行 的中断。这通常是可取的,但如果你想避免这种情况,你可以简单地使用 _disable_irq()/_enable_irq() 禁用所有中断。这将防止任务切换 中断。

禁用中断是蛮力操作,对系统实时行为的影响甚至比调度程序锁定的影响更大。通常它应该只在很短的时间内完成(调度程序锁定也应该如此)。

不要直接从用户代码更改任务的优先级。大多数 RTOS 都提供了使我们能够做到这一点的 API,但这种风格很糟糕,因为它产生的问题多于它能解决的问题。一个例外是当某些 RTOS 在内部运行时(例如,具有优先级继承的互斥锁以避免某些多任务问题)。

我想您只想在系统的启动阶段或运行时的另一个非常特殊的阶段拥有更长的临界区。否则,你真的应该听听@Clifford 的评论并质疑你的优先分配和任务分解

如果您仅在 init/power-up 阶段需要该连续时间段,这也是通过良好的任务设计实现的典型情况。在那种情况下,你需要的是运行级别管理.

运行级别管理

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

在填充运行级别管理配置之前,您可以自己画一个 sequence diagram 检查在哪些点,任务必须出于任何原因等待其他任务。 通常对于每个任务,只有少数运行级别是相关的——并且每个运行级别,相关任务的集合也可能很小。 因此,您可能想添加一个小辅助函数,例如 WaitForRunlevelNumber(N),它带有一个循环,可以自动处理那些不相关的运行级别。

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