В ряде случаев наследование приоритетов может оказаться не самым оптимальным решением. Примером здесь может служить ситуация, когда один высокоприоритетный поток разделяет много ресурсов с низкоприоритетными потоками — по одному ресурсу на каждый поток. В такой ситуации может возникнуть положение, когда много низкоприоритетных потоков (вытесненных) выстроятся перед высокоприоритетным. Но тогда длинный ряд последовательных операций вытеснения («поштучно») и наследования приоритетов блокирующих потоков может привести к тому, что не хватит времени до окончания критического срока выполнения потока высокого приоритета, пока ОС будет анализировать ситуацию и последовательно проводить протокол наследования приоритетов.
Именно для таких ситуаций и предназначен протокол граничного приоритета. В соответствии с этим протоколом примитив синхронизации (в нашем рассмотрении это мьютекс) наделяется собственным фиксированным приоритетом, а приоритет любого потока, захватившего этот мьютекс, поднимается до предустановленного граничного уровня приоритета мьютекса.
Определение протокола защиты от инверсии приоритетов
int pthread_mutexattr_setprotocol(
pthread_mutexattr_t* attr, int protocol);
int pthread_mutexattr_getprotocol(
pthread_mutexattr_t* attr, int* protocol);
Эти функции устанавливают/считывают протокол, который реализуется мьютексом для защиты от инверсии приоритетов. Переменная protocol
PTHREAD_PRIO_INHERIT
PTHREAD_PRIO_PROTECT
prioceiling, возвращаемого функцией pthread_mutexattr_getprioceiling(). Таким образом, установка этого значения в качестве протокола мьютекса приводит к реализации протокола граничного приоритета для защиты от инверсии приоритетов.Внешний доступ
int pthread_mutexattr_setpshared(
pthread_mutexattr_t* attr, int pshared);
int pthread_mutexattr_getpshared(
const pthread_mutexattr_t* attr, int* pshared);
Эти функции устанавливают/считывают внутреннее поле атрибутной записи мьютекса, определяющее, возможен ли доступ к мьютексу из потоков, запущенных вне процесса, в котором был создан и инициализирован мьютекс. Параметр pshared
PTHREAD_PROCESS_SHARED
PTHREAD_PROCESS_PRIVATE
Разрешение рекурсивного захвата
int pthread_mutexattr_setrecursive(
pthread_mutexattr_t* attr, int recursive);
int pthread_mutexattr_getrecursive(
const pthread_mutexattr_t* attr, int* recursive);
Функции устанавливают/считывают в атрибутной записи мьютекса признак, определяющий, может ли поток, ранее захвативший мьютекс (его владелец), захватить его еще раз (естественно, что любой другой поток захватить такой мьютекс уже не может и он будет заблокирован). Режим реализован для возможности рекурсивного вызова процедур в потоке. Необходимо помнить, что при рекурсивном захвате мьютекс должен быть освобожден столько раз, сколько раз он был захвачен. Параметр recursive может принимать следующие значения:
PTHREAD_RECURSIVE_ENABLE