EAGAIN
— недостаточно системных ресурсов для захвата мьютекса;
EBUSY
— мьютекс mutex
уже захвачен;
EINVAL
— некорректное значение параметра mutex.
#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t* mutex,
const struct timespec* abs_timeout);
Функция проверяет, свободен ли мьютекс (mutex
), и если да, то поток, в котором вызвана функция, захватывает этот мьютекс. Если мьютекс уже захвачен, вызвавший поток блокируется до освобождения мьютекса либо до наступления времени, указанного в аргументе abs_timeout
. Если это время уже наступило, поток не блокируется вообще, но захват все-таки произойдет, если мьютекс свободен.
Наступление времени определяется по часам REALTIME_CLOCK
, когда значение часов оказывается равным или большим значения, указанного в abs_timeout
. Тип данных timespec определен в файле <time.h>
.
Если мьютекс создан с атрибутом протокола PRIO_INHERIT
, то после выхода потока из блокировки на мьютексе по тайм-ауту приоритет владельца мьютекса подвергается пересмотру в соответствии с приоритетами потоков, оставшихся в очереди на захват мьютекса.
Возвращаемые значения:
EOK
— успешное завершение;
EAGAIN
— недостаточно системных ресурсов для захвата мьютекса;
EDEADLK
— вызывающий поток уже владеет мьютексом, который не поддерживает рекурсивный захват (режим контроля ошибок);
EINVAL
— мьютекс использует протокол граничного приоритета для предотвращения инверсии (атрибут protocol
установлен в значение PTHREAD_PRIO_PROTECT
), но приоритет вызвавшего потока выше граничного приоритета, присвоенного мьютексу; поток должен быть блокирован (мьютекс не свободен), а значение поля abs_timeout
, показывающее количество наносекунд, меньше нуля или больше 1000 миллионов; переменная, на которую указывает mutex
, не является инициированным объектом — мьютексом.
ETIMEDOUT
— мьютекс не может быть захвачен, поскольку указанный тайм-аут истек.
Освобождение мьютекса
int pthread_mutex_unlock(pthread_mutex_t* mutex);
Функция pthread_mutex_unlock()
освобождает мьютекс, на который ссылается переменная mutex
. Вызвавший поток должен быть владельцем мьютекса. Если есть потоки, блокированные в ожидании освобождения мьютекса, то поток с наивысшим приоритетом (или при равных приоритетах дольше всех ждавший) выходит из блокированного состояния и становится владельцем мьютекса.
Для мьютексов, разрешающих рекурсивный захват, функция освобождения должна вызываться столько же раз, сколько и функция захвата.
Возвращаемые значения:
EOK
— успешное завершение;
EINVAL
— переменная, на которую указывает mutex
, не является инициализированным объектом — мьютексом;
EPERM
— вызвавший поток не является владельцем мьютекса.
Разрушение объекта мьютекс
int pthread_mutex_destroy(pthread_mutex_t* mutex);
Вызов разрушает объект мьютекс, на который указывает переменная mutex
. После чего эта переменная не может быть использована без предварительного вызова pthread_mutex_init ()
.
Возвращаемые значения:
EOK
— успешное завершение;
EBUSY
-
мьютекс захвачен и не может быть разрушен до освобождения;
EINVAL
— переменная, на которую указывает mutex
, не является инициированным объектом - мьютексом.
Операции, не поддерживаемые POSIX
В native QNX API есть ряд функций работы с мьютексом, которые не определены POSIX-стандартом, однако они могут оказаться весьма полезными. Поскольку тип POSIX-мьютекса порождается от sync_t
, то вполне возможно использование комбинации функций, определенных POSIX, и «родных» native-функций QNX. Однако необходимо помнить, что в таком случае ни о какой межсистемной совместимости говорить уже не приходится.
#include <sys/neutrino.h>
int SyncMutexRevive(sync_t* sync);
int SyncMutexRevive_r(sync_t* sync);
Эти функции[36] предназначены для восстановления мьютекса, который находится в состоянии блокирования DEAD
. Мьютекс попадает в состояние DEAD
, когда память, использованная при захвате мьютекса, освобождается. Такое может произойти, например, когда умирает поток, захвативший мьютекс, расположенный в разделяемой памяти. В результате вызова вызвавший поток становится владельцем мьютекса, и его счетчик захватов устанавливается в 1 для рекурсивного мьютекса.
Ошибки выполнения функции:
ЕFAULT
— ошибка при обращении к указанным в аргументах переменным;
EINVAL
— указанный объект синхронизации не существует или не находится в состоянии DEAD
;
ETIMEDOUT
— отмена вызова по тайм-ауту ядра (устанавливается вызовом TimerTimeout()
).
Определить состояние мьютекса как DEAD
можно с помощью функции SyncMutexEvent()
, которая определяет событие, связанное со «смертью» мьютекса.
#include <sys/neutrino.h>
int SyncMutexEvent(sync_t* sync, struct sigevent* event);
int SyncMutexEvent_r(sync_t* sync, struct sigevent* event);
Данная функция предназначена для установки обработчика ситуации, когда мьютекс попадает в