1 /*-------------------------------------------------------------------------
2  *
3  * pthread_barrier_wait.c
4  *    Implementation of pthread_barrier_t support for platforms lacking it.
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  *    src/port/pthread_barrier_wait.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "c.h"
15 
16 #include "port/pg_pthread.h"
17 
18 int
pthread_barrier_init(pthread_barrier_t * barrier,const void * attr,int count)19 pthread_barrier_init(pthread_barrier_t *barrier, const void *attr, int count)
20 {
21 	int			error;
22 
23 	barrier->sense = false;
24 	barrier->count = count;
25 	barrier->arrived = 0;
26 	if ((error = pthread_cond_init(&barrier->cond, NULL)) != 0)
27 		return error;
28 	if ((error = pthread_mutex_init(&barrier->mutex, NULL)) != 0)
29 	{
30 		pthread_cond_destroy(&barrier->cond);
31 		return error;
32 	}
33 
34 	return 0;
35 }
36 
37 int
pthread_barrier_wait(pthread_barrier_t * barrier)38 pthread_barrier_wait(pthread_barrier_t *barrier)
39 {
40 	bool		initial_sense;
41 
42 	pthread_mutex_lock(&barrier->mutex);
43 
44 	/* We have arrived at the barrier. */
45 	barrier->arrived++;
46 	Assert(barrier->arrived <= barrier->count);
47 
48 	/* If we were the last to arrive, release the others and return. */
49 	if (barrier->arrived == barrier->count)
50 	{
51 		barrier->arrived = 0;
52 		barrier->sense = !barrier->sense;
53 		pthread_mutex_unlock(&barrier->mutex);
54 		pthread_cond_broadcast(&barrier->cond);
55 
56 		return PTHREAD_BARRIER_SERIAL_THREAD;
57 	}
58 
59 	/* Wait for someone else to flip the sense. */
60 	initial_sense = barrier->sense;
61 	do
62 	{
63 		pthread_cond_wait(&barrier->cond, &barrier->mutex);
64 	} while (barrier->sense == initial_sense);
65 
66 	pthread_mutex_unlock(&barrier->mutex);
67 
68 	return 0;
69 }
70 
71 int
pthread_barrier_destroy(pthread_barrier_t * barrier)72 pthread_barrier_destroy(pthread_barrier_t *barrier)
73 {
74 	pthread_cond_destroy(&barrier->cond);
75 	pthread_mutex_destroy(&barrier->mutex);
76 	return 0;
77 }
78