In cases where you must wait for a number of tasks to be completed before an overall task can proceed, barrier synchronization can be used. POSIX threads specifies a synchronization object called a barrier, along with barrier functions. The functions create the barrier, specifying the number of threads that are synchronizing on the barrier, and set up threads to perform tasks and wait at the barrier until all the threads reach the barrier. When the last thread arrives at the barrier, all the threads resume execution.
See Parallelizing a Loop on a Shared-Memory Parallel Computer for more about barrier synchronization.
Use pthread_barrier_init(3C) to allocate resources for a barrier and initialize its attributes.
int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *restrict attr, unsigned count);
#include <pthread.h> pthread_barrier_t barrier; pthread_barrierattr_t attr; unsigned count; int ret; ret = pthread_barrier_init(&barrier, &attr, count);
The pthread_barrier_init() function allocates any resources required to use the barrier referenced by barrier and initializes the barrier with attributes referenced by attr. If attr is NULL, the default barrier attributes are used; the effect is the same as passing the address of a default barrier attributes object. The count argument specifies the number of threads that must call pthread_barrier_wait() before any of them successfully return from the call. The value specified by count must be greater than 0.
pthread_barrier_init() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: The value specified by count is equal to 0, or the value specified by attr is invalid
EAGAIN
Description: The system lacks the necessary resources to initialize another barrier.
ENOMEM
Description: Insufficient memory exists to initialize the barrier.
EBUSY
Description: There was an attempt to destroy a barrier while it is in use (for example, while being used in a pthread_barrier_wait() call) by another thread.
Use pthread_barrier_wait(3C) to synchronize threads at a specified barrier. The calling thread blocks until the required number of threads have called pthread_barrier_wait() specifying the barrier. The number of threads is specified in the pthread_barrier_init() function.
When the required number of threads have called pthread_barrier_wait() specifying the barrier, the constant PTHREAD_BARRIER_SERIAL_THREAD is returned to one unspecified thread and 0 is returned to each of the remaining threads. The barrier is then reset to the state it had as a result of the most recent pthread_barrier_init() function that referenced it.
int pthread_barrier_wait(pthread_barrier_t *barrier);
#include <pthread.h> pthread_barrier_t barrier; int ret; ret = pthread_barrier_wait(&barrier);
When pthread_barrier_wait() completes successfully, the function returns PTHREAD_BARRIER_SERIAL_THREAD, which is defined in pthread.h, for one arbitrary thread synchronized at the barrier. The function returns zero for each of the other threads. Otherwise an error code is returned.
EINVAL
Description: The value specified by barrier does not refer to an initialized barrier object.
When a barrier is no longer needed, it should be destroyed. Use the pthread_barrier_destroy(3C) function to destroy the barrier referenced by barrier and release any resources used by the barrier.
int pthread_barrier_destroy(pthread_barrier_t *barrier);
#include <pthread.h> pthread_barrier_t barrier; int ret; ret = pthread_barrier_destroy(&barrier);
pthread_barrier_destroy() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of barrier was not valid.
EBUSY
Description: An attempt was made to destroy a barrier while it is in use (for example, while being used in a pthread_barrier_wait() by another thread.
The pthread_barrierattr_init(3C) function initializes a barrier attributes object attr with the default values for the attributes defined for the object by the implementation. Currently, only the process-shared attribute is provided, and the pthread_barrierattr_getpshared() and pthread_barrierattr_setpshared() functions are used to get and set the attribute.
After a barrier attributes object has been used to initialize one or more barriers, any function affecting the attributes object (including destruction) does not affect any previously initialized barrier.
int pthread_barrierattr_init(pthread_barrierattr_t *attr);
#include <pthread.h> pthread_barrierattr_t attr; int ret; ret = pthread_barrierattr_init(&attr);
pthread_barrierattr_init() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
ENOMEM
Description: Insufficient memory exists to initialize the barrier attributes object.
The pthread_barrierattr_setpshared() function sets the process-shared attribute in an initialized attributes object referenced by attr. The process-shared attribute can have the following values:
The barrier can only be operated upon by threads created within the same process as the thread that initialized the barrier. This is the default value of the process-shared attribute.
The barrier can be operated upon by any thread that has access to the memory where the barrier is allocated.
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);
pthread_barrierattr_setpshared() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of attr was not valid, or the new value specified for the pshared is not valid.
The pthread_barrierattr_getpshared(3C) function obtains the value of the process-shared attribute from the attributes object referenced by attr. The value is set by the pthread_barrierattr_setpshared() function.
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict attr, int *restrict pshared);
pthread_barrierattr_getpshared() returns zero after completing successfully, and stores the value of the process-shared attribute of attr into the object referenced by the pshared parameter. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of attr was not valid.
The pthread_barrierattr_destroy() function destroys a barrier attributes object. A destroyed attr attributes object can be reinitialized using pthread_barrierattr_init().
After a barrier attributes object has been used to initialize one or more barriers, destroying the object does not affect any previously initialized barrier.
#include <pthread.h> int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);
pthread_barrierattr_destroy() returns zero after completing successfully. Any other return value indicates that an error occurred. If the following condition occurs, the function fails and returns the corresponding value.
EINVAL
Description: Indicates that the value of attr was not valid.