В ряде случаев наследование приоритетов может оказаться не самым оптимальным решением. Примером здесь может служить ситуация, когда один высокоприоритетный поток разделяет много ресурсов с низкоприоритетными потоками — по одному ресурсу на каждый поток. В такой ситуации может возникнуть положение, когда много низкоприоритетных потоков (вытесненных) выстроятся перед высокоприоритетным. Но тогда длинный ряд последовательных операций вытеснения («поштучно») и наследования приоритетов блокирующих потоков может привести к тому, что не хватит времени до окончания критического срока выполнения потока высокого приоритета, пока ОС будет анализировать ситуацию и последовательно проводить протокол наследования приоритетов.

Именно для таких ситуаций и предназначен протокол граничного приоритета. В соответствии с этим протоколом примитив синхронизации (в нашем рассмотрении это мьютекс) наделяется собственным фиксированным приоритетом, а приоритет любого потока, захватившего этот мьютекс, поднимается до предустановленного граничного уровня приоритета мьютекса.

<p>Определение протокола защиты от инверсии приоритетов</p>

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(). Таким образом, установка этого значения в качестве протокола мьютекса приводит к реализации протокола граничного приоритета для защиты от инверсии приоритетов.

<p>Внешний доступ</p>

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 — любой поток из любого процесса в системе, который может получить доступ к синхронизирующему объекту (для этого придется использовать какой-либо из методов IPC, возможно shared memory), может использовать его по назначению.

PTHREAD_PROCESS_PRIVATE (значение по умолчанию) — мьютекс может использоваться только потоками, порожденными в том же процессе, где был инициализирован мьютекс. В документации сказано: попытка захвата мьютекса с таким значением параметра доступа к потокам из «чужого» процесса приведет к неопределенному результату. На практике же функция захвата возвращает управление в любом случае, независимо от того, был ли уже захвачен мьютекс другим потоком или нет (как будто происходит нормальный захват). Состояние мьютекса при этом никак не меняется.

<p>Разрешение рекурсивного захвата</p>

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 — разрешает рекурсивный захват мьютекса;

Перейти на страницу:

Все книги серии High tech

Нет соединения с сервером, попробуйте зайти чуть позже