5.5.5 Priority-aware mutexes

#if defined (_POSIX_THREAD_PRIO_PROTECT)

|| defined (_POSIX_THREAD_PRIO_INHERIT)

int pthread_mutexattr_getprotocol (

const pthread_mutexattr_t *attr, int *protocol);

int pthread_mutexattr_setprotocol (

pthread_mutexattr_t *attr, int protocol);

#endif

#ifdef _POSIX_THREAD_PRIO_PROTECT

int pthread_mutexattr_getprioceiling (

const pthread_attr_t *attr, int *prioceiling);

int pthread_mutexattr_setprioceiling (

pthread_mutexattr_t *attr, int prioceiling);

int pthread_mutex_getprioceiling (

const pthread_mutex_t *mutex, int *prioceiling);

int pthread_mutex_setprioceiling (

pthread_mutex_t *mutex,

int prioceiling, int *old_ceiling);

#endif

Pthreads provides several special mutex attributes that can help to avoid priority inversion deadlocks. Locking, or waiting for, a mutex with one of these attributes may change the priority of the thread — or the priority of other threads— to ensure that the thread that owns the mutex cannot be preempted by another thread that needs to lock the same mutex.

These mutex attributes may not be supported by your implementation of Pthreads, because they are optional features. If your code needs to function with or without these options, you can conditionally compile references based on the feature test macros _POSIX_THREAD_PRIO_PROTECT or _POSIX_THREAD_PRIO_ INHERIT, defined in <unistd.h>, or you can call sysconf during program execution to check for SC_THREAD_PRIO_PROTECT or SC_THREAD_PRIO_INHERIT.

Once you've created a mutex using one of these attributes, you can lock and unlock the mutex exactly like any other mutex. As a consequence, you can easily convert any mutex you create by changing the code that initializes the mutex. (You must call pthread_mutex_init, however, because you cannot statically initialize a mutex with nondefault attributes.)

'Priority ceiling' protocol means that while a thread owns the mutex, it runs at the specified priority.

If your system defines _POSIX_THREAD_PRIO_PROTECT then it supports the protocol and prioceiling attributes. You set the protocol attribute by calling pthread_mutexattr_setprotocol. If you set the protocol attribute to the value PTHREAD_PRIO_PROTECT, then you can also specify the priority ceiling for mutexes created using the attributes object by setting the prioceiling attribute.

You set the prioceiling attribute by calling the function pthread_mutexattr_ setprioceiling. When any thread locks a mutex defined with such an attributes object, the thread's priority will be set to the priority ceiling of the mutex, unless the thread's priority is already the same or higher. Note that locking the mutex in a thread running at a priority above the priority ceiling of the mutex breaks the protocol, removing the protection against priority inversion.

'Priority inheritance' means that when a thread waits on a mutex owned by a lower-priority thread,the priority of the owner is increased to that of the waiter.

If your system defines _POSIX_THREAD_PRIO_INHERIT then it supports the protocol attribute. If you set the protocol attribute to the value PTHREAD_PRIO_ INHERIT, then no thread holding the mutex can be preempted by another thread with a priority lower than that of any thread waiting for the mutex. When any thread attempts to lock the mutex while a lower-priority thread holds the mutex, the priority of the thread currently holding the mutex will be raised to the priority of the waiter as long as it owns the mutex.

If your system does not define either _POSIX_THREAD_PRIO_PROTECT or _POSIX_ THREAD_PRIO_INHERIT then the protocol attribute may not be defined. The default value of the protocol attribute (or the effective value ifthe attribute isn't defined) is POSIX_PRIO_NONE, which means that thread priorities are not modified by the act of locking (or waiting for) a mutex.

5.5.5.1 Priority ceiling mutexes

The simplest of the two types of 'priority aware' mutexes is the priority ceiling (or 'priority protection') protocol (Figure 5.3). When you create a mutex using a priority ceiling, you specify the highest priority at which a thread will ever be running when it locks the mutex. Any thread locking that mutex will have its

FIGURE 5.3 Priority ceiling mutex operation

priority automatically raised to that value, which will allow it to finish with the mutex before it can be preempted by any other thread that might try to lock the mutex. You can also examine or modify the priority ceiling of a mutex that was created with the priority ceiling (protect) protocol.

A priority ceiling mutex is not useful within a library that can be called by threads you don't control. If any thread that is running at a priority above the ceiling locks the priority ceiling mutex, the protocol is broken. This doesn't necessarily guarantee a priority inversion, but it removes all protection against priority inversion. Since the priority ceiling protocol adds overhead to each mutex operation compared to a normal 'unprotected' mutex, you may have wasted processor time accomplishing nothing.

Priority ceiling is perfect for an embedded realtime application where the developers control all synchronization within the system. The priority ceiling can be safely determined when the code is designed, and you can avoid priority inversion with a relatively small cost in performance compared to more general solutions. Of course it is always most efficient to avoid priority inversion, either by avoiding priority scheduling or by using any given mutex only within threads of equal priority. Equally, of course, these alternatives rarely prove practical when you need them most.

You can use priority ceiling within almost any main program, even when you don't control the code in libraries you use. That's because while it is common for threads that call into library functions to lock library mutexes, it is not common for threads created by a library to call into application code and lock application mutexes. If you use a library that has 'callbacks' into your code, you must either ensure that those callbacks (and any functions they call) don't use the priority ceiling mutexes or that no thread in which the callback might be invoked will run at a priority above the ceiling priority of the mutex.

5.5.5.2 Priority inheritance mutexes

The other Pthreads mutex protocol is priority inheritance. In the priority inheritance

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату