4.5.1 Mutex
A mutex is an object for mutual exclusion control among tasks that use shared resources. Priority inheritance mutexes and priority ceiling mutexes are supported, as tools for managing the problem of unbounded priority inversion that can occur in mutual exclusion control. Functions are provided for creating and deleting a mutex, locking and unlocking a mutex, and referencing mutex status. A mutex is identi.ed by an ID number called a mutex ID.
A mutex has a status (locked or unlocked) and a queue for tasks waiting to lock the mutex. For each mutex, T-Kernel keeps track of the tasks locking it; and for each task, it keeps track of the mutexes it has locked. Before a task uses a resource, it locks a mutex corresponding to that resource. If the mutex is already locked by another task, the task waits for the mutex to become unlocked. Tasks in mutex lock waiting state are put in the mutex queue. When a task .nishes with a resource, it unlocks the mutex. A mutex with TA_INHERIT(= 0×02) specified as mutex attribute supports priority inheritance protocol, while one with TA_CEILING(= 0×03) specified supports priority ceiling protocol. When a priority ceiling mutex is created, a ceiling priority is assigned to it, indicating the base priority of the task having the highest base priority among the tasks able to lock that mutex. If a task having a higher base priority than the ceiling priority of the mutex tries to lock it, error code E_ILUSE is returned. If tk_chg_pri is issued in an attempt to set the base priority of a task locking a priority ceiling mutex to a value higher than the ceiling priority of that mutex, E_ILUSE is returned by the tk_chg_pri system call.
When these protocols are used, unbounded priority inversion is prevented by changing the current priority of a task in a mutex operation. Strict adherence to the priority inheritance protocol and priority ceiling protocol requires that the task current priority must always be changed to match the peak value of the following priorities. This is called strict priority control.
- The task base priority.
- When tasks lock priority inheritance mutexes, the current priority of the task having the highest current priority of the tasks waiting for those mutexes.
- When tasks lock priority ceiling mutexes, the ceiling priority of the mutex having the highest ceiling priority among those mutexes.
Note that when the current priority of a task waiting for a priority inheritance mutex changes as the result of a base priority change brought about by mutex operation or tk_chg_pri, it may be necessary to change the current priority of the task locking that mutex. This is called dynamic priority inheritance. Further, if this task is waiting for another priority inheritance mutex, dynamic priority inheritance processing may be necessary also for the task locking that mutex.
The T-Kernel speci.cation de.nes, in addition to the above strict priority control, a simpli.ed priority control limiting the situations in which the current priority is changed. The choice between the two is an implementation-dependent matter. In the simpli.ed priority control, whereas all changes in the direction of raising the task current priority are carried out, changes in the direction of lowering that priority are made only when a task is no longer locking any mutexes. (In this case the task current priority reverts to the base priority.) More speci.cally, processing to change the current priority is needed only in the following circumstances.
- When a task with a higher current priority than that of the task locking a priority inheritance mutex starts waiting for that mutex.
- When a task waiting for a priority inheritance mutex is changed to a higher current priority than that of the task locking that mutex.
- When a task locks a priority ceiling mutex having a higher ceiling priority than the task’s current priority.
- When a task is no longer locking any mutexes.
When the current priority of a task is changed in connection with a mutex operation, the following processing is performed. If the task whose priority changed is in a run state, the task precedence is changed in accord with the new priority. Its precedence among other tasks having the same priority is implementation-dependent. Likewise, if the task whose priority change diswaiting in a queue of some kind, its order in that queue is changed based on its new priority. Its order among other tasks having the same priority is implementation-dependent.
When a task terminates and there are mutexes still locked by that task, all the mutexes are unlocked. The order in which multiple locked mutexes are unlocked is implementation-dependent. See the description of tk_unl_mtx for the specific processing involved.
A TA_TFIFO attribute mutex or TA_TPRI attribute mutex has functionality equivalent to that of a semaphore with a maximum of one resource (binary semaphore). The main differences are that a mutex can be unlocked only by the task that locked it, and a mutex is automatically unlocked when the task locking it terminates.
The term “priority ceiling protocol” is used here in a broad sense. The protocol described here is not the same as the algorithm originally proposed. Strictly speaking, it is what is otherwise referred to as a highest locker protocol or by other names.
When the change in current priority of a task due to a mutex operation results in that task’s order being changed in a priority-based queue, it may be necessary to release the waiting state of other tasks waiting for that task or for that queue.
The precedence of tasks having the same priority as the result of a change in task current priority in a mutex operation is left as implementation-dependent, for the following reason.
Depending on the application, the mutex function may lead to frequent changes in current priority. It would not be desirable for this to result in constant task switching, which is what would happen if the precedence were made the lowest each time among tasks of the same priority. Ideally task precedence rather than priority should be inherited, but that results in large overhead in implementation. This aspect of the speci.cation is therefore made an implementation-dependent matter.

Comments