互斥锁陷阱:优先级反转、死锁

摘自:

Mastering the FreeRTOS 7.3 Mutexes (and Binary Semaphores)

Priority Inversion

This Figure demonstrates one of the potential pitfalls of using a mutex to provide mutual exclusion. The sequence of execution depicted shows the higher priority Task 2 having to wait for the lower priority Task 1 to give up control of the mutex. A higher priority task being delayed by a lower priority task in this manner is called ‘priority inversion’. This undesirable behavior would be exaggerated further if a medium priority task started to execute while the high priority task was waiting for the semaphore—the result would be a high priority task waiting for a low priority task—without the low priority task even being able to execute. This
worst case scenario is shown in Figure below:

Figure.  A worst case priority inversion scenario

Priority inversion can be a significant problem, but in small embedded systems it can often be avoided at system design time, by considering how resources are accessed.


Priority Inheritance

OS mutexes and binary semaphores are very similar—the difference being that mutexes include a basic ‘priority inheritance’ mechanism, whereas binary semaphores do not. Priority inheritance is a scheme that minimizes the negative effects of priority inversion. It does not ‘fix’ priority inversion, but merely lessens its impact by ensuring that the inversion is always time bounded. However, priority inheritance complicates system timing analysis, and it is not good practice to rely on it for correct system operation.

Priority inheritance works by temporarily raising the priority of the mutex holder to the priority of the highest priority task that is attempting to obtain the same mutex. The low priority task that holds the mutex ‘inherits’ the priority of the task waiting for the mutex. This is demonstrated by Figure below. The priority of the mutex holder is reset automatically to its original value when it gives the mutex back.

Figure. Priority inheritance minimizing the effect of priority inversion

As just seen, priority inheritance functionality effects the priority of tasks that are using the mutex. For that reason, mutexes must not be used from an interrupt service routines.


Deadlock (or Deadly Embrace)

Deadlock’ is another potential pitfall of using mutexes for mutual exclusion. Deadlock is sometimes also known by the more dramatic name ‘deadly embrace’.

Deadlock occurs when two tasks cannot proceed because they are both waiting for a resource that is held by the other. Consider the following scenario where Task A and Task B both need to acquire mutex X and mutex Y in order to perform an action:

1. Task A executes and successfully takes mutex X.
2. Task A is pre-empted by Task B.
3. Task B successfully takes mutex Y before attempting to also take mutex X—but mutex X is held by Task A so is not available to Task B. Task B opts to enter the Blocked state to wait for mutex X to be released.
4. Task A continues executing. It attempts to take mutex Y—but mutex Y is held by Task B, so is not available to Task A. Task A opts to enter the Blocked state to wait for mutex Y to be released.

At the end of this scenario, Task A is waiting for a mutex held by Task B, and Task B is waiting for a mutex held by Task A. Deadlock has occurred because neither task can proceed.
最简单的死锁场景:自死锁。一个任务试图去获得一个自己已经持有的锁。


As with priority inversion, the best method of avoiding deadlock is to consider its potential at design time, and design the system to ensure that deadlock cannot occur. In particular, and as previously stated in this book, it is normally bad practice for a task to wait indefinitely (without a time out) to obtain a mutex.

Instead, use a timeout that is a little longer than the maximum time it is expected to have to wait for the mutex—then failure to obtain the mutex within that time will be a symptom of a design error, which might be a deadlock.

In practice, deadlock is not a big problem in small embedded systems, because the system designers can have a good understanding of the entire application, and so can identify and remove the areas where it could occur.

总结:

1、优先级反转和死锁问题要在设计阶段避免

2、对持锁时间做限制;超时释放锁

原文地址:https://www.cnblogs.com/rockyching2009/p/13139434.html