A more severe problem with fixed priority scheduling is called
Priority inversion occurs when low-priority thread acquires a shared resource (such as a mutex), and is preempted by a high-priority thread that then blocks on that same resource. With only two threads, the low-priority thread would then be allowed to run, eventually (we assume) releasing the mutex. However, if a third thread with a priority between those two is ready to run, it can prevent the low-priority thread from running. Because the low-priority thread holds the mutex that the high-priority thread needs, the middle-priority thread is also keeping the higher-priority thread from running.
There are a number of ways to prevent priority inversion. The simplest is to avoid using realtime scheduling, but that's not always practical. Pthreads provides several mutex locking protocols that help avoid priority inversion,
I Most threaded programs do not need realtime scheduling.
A final problem is that priority scheduling isn't completely portable. Pthreads defines the priority scheduling features under an option, and many implementations that are not primarily intended for realtime programming may choose not to support the option. Even if the option is supported, there are many important aspects of priority scheduling that are not covered by the standard. When you use system contention scope, for example, where your threads may compete directly against threads within the operating system, setting a high priority on your threads might prevent kernel I/O drivers from functioning on some systems.
Pthreads does not specify a thread's default scheduling policy or priority, or how the standard scheduling policies interact with nonstandard policies. So when you set the scheduling policy and priority of your thread, using "portable" interfaces, the standard provides no way to predict how that setting will affect any other threads in the process or the system itself.
If you really need priority scheduling, then use it — and be aware that it has special requirements beyond simply Pthreads. If you need priority scheduling, keep the following in mind:
1. Process contention scope is "nicer" than system contention scope, because you will not prevent a thread in another process, or in the kernel, from running.
2. SCHED_RR is "nicer" than SCHED_FIFO, and slightly more portable, because SCHED_RR threads will be preempted at intervals to share the available processor time with other threads at the same priority.
3. Lower priorities for SCHED_FIFO and SCHED_RR policies are nicer than higher priorities, because you are less likely to interfere with something else that's important.
Unless your code really needs priority scheduling, avoid it. In most cases, introducing priority scheduling will cause more problems than it will solve.
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.