typedef struct {
unsigned int barrier;
unsigned int count;
pthread_mutex_t lock;
pthread_cond_t bcond;
} pthread_barrier_t;
Выводы можно сделать самостоятельно.
Также несколько загадочно выглядит тот факт, что согласно документации QNX 6.2.1 все функции работы с барьером и его атрибутами описаны в заголовочном файле
, за исключением двух функций
pthread_barrier_wait
и
pthread_barrierattr_setpshared
, о которых говорится, что они описаны в файле
! Но если заглянуть в заголовочные файлы, то выясняется, что можно спокойно использовать для абсолютно всех функций работы с барьером либо заголовочный файл
, либо
.
Операции с барьерами
Параметры барьера
Следующие функции инициализируют и разрушают блок параметров барьера:
int pthread_barrierattr_init(pthread_barrierattr_t* attr);
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr);
Функция инициализации возвращает следующие значения:
EOK
— успешное выполнение;
ENOMEM
— недостаточно памяти для инициализации атрибутов барьера.
Функция разрушения атрибутов объекта возвращает значения:
EOK
— успешное выполнение;
EINVAL
— передан неверный объект атрибутов барьера
attr
.
Параметры барьера описываются типом
pthread_barrierattr_t
и аналогично другим типам синхронизации используются в момент инициализации элемента синхронизации. Фактически единственным атрибутом барьера является модификатор доступа к барьеру из других процессов:
int pthread_barrierattr_setpshared(
pthread_barrierattr_t* attr, int pshared);
int pthread_barrierattr_getpshared(
const pthread_barrierattr_t* attr, int* pshared);
По умолчанию атрибуты барьера запрещают доступ к элементу синхронизации из других процессов.
Обе функции могут возвращать следующие значения:
EOK
— успешное выполнение;
EINVAL
— одно или оба из переданных функции значений неверны.
Инициализация и разрушение барьера
int pthread_barrier_init(pthread_barrier_t* barrier,
const pthread_barrierattr_t* attr, unsigned int count);
Функция инициализирует объект синхронизации типа барьер, после чего его можно использовать. В атрибутах барьера устанавливается (или запрещается) возможность доступа к барьеру из других процессов. По умолчанию такой доступ запрещен. Для того чтобы изменить возможность доступа к созданному ранее барьеру, его необходимо разрушить, установить соответствующий атрибут и инициализировать барьер повторно. Параметр
count
показывает, какое количество потоков будет ожидать на барьере до их освобождения.
Возвращаемые значения:
EOK
— успешное выполнение;
EAGAIN
— системе не хватает ресурсов для инициализации барьера;
EBUSY
— попытка инициализации уже инициализированного барьера;
EFAULT
— сбой произошел при обращении ядра к аргументам;
EINVAL
—
attr
указывает на неинициализированное значение атрибутов.
int pthread_barrier_destroy(pthread_barrier_t* barrier);
Функция разрушает барьер, после чего соответствующий элемент синхронизации
barrier
не может использоваться без повторной его инициализации.
Возвращаемые значения:
EOK
— успешное выполнение;
EBUSY
— в настоящее время есть потоки, блокированные на барьере;
EINVAL
— неинициализированный объект
barrier
.
Ожидание на барьере
Функция ожидания (синхронизации) на барьере:
int pthread_barrier_wait(pthread_barrier_t* barrier);
Вызов этой функции приводит к блокированию потока до тех пор, пока на барьере не накопится количество заблокированных потоков, определенное ранее при вызове функции
pthread_barrier_init
.
Необходимо с особой осторожностью относиться к использованию барьеров для остановки и синхронизации потоков разных приоритетов. Поскольку потоки, ожидающие у барьера, находятся в блокировке на условной переменной (внутренней), то система никак не отслеживает эффекты, связанные с возможной инверсией приоритетов.
Если поток, блокированный на барьере, получает сигнал, для которого определен обработчик, то обработчик сигнала выполняется, но по завершении его выполнения поток вновь блокируется до выполнения условия барьера.