mirror of https://github.com/postgres/postgres
Supply a simple implementation of the missing pthread_barrier_t type and functions, for macOS. Discussion: https://postgr.es/m/20200227180100.zyvjwzcpiokfsqm2%40alap3.anarazel.depull/64/head
parent
547f04e734
commit
44bf3d5083
@ -0,0 +1,41 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* Declarations for missing POSIX thread components. |
||||
* |
||||
* Currently this supplies an implementation of pthread_barrier_t for the |
||||
* benefit of macOS, which lacks it. These declarations are not in port.h, |
||||
* because that'd require <pthread.h> to be included by every translation |
||||
* unit. |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#ifndef PG_PTHREAD_H |
||||
#define PG_PTHREAD_H |
||||
|
||||
#include <pthread.h> |
||||
|
||||
#ifndef HAVE_PTHREAD_BARRIER_WAIT |
||||
|
||||
#ifndef PTHREAD_BARRIER_SERIAL_THREAD |
||||
#define PTHREAD_BARRIER_SERIAL_THREAD (-1) |
||||
#endif |
||||
|
||||
typedef struct pg_pthread_barrier |
||||
{ |
||||
bool sense; /* we only need a one bit phase */ |
||||
int count; /* number of threads expected */ |
||||
int arrived; /* number of threads that have arrived */ |
||||
pthread_mutex_t mutex; |
||||
pthread_cond_t cond; |
||||
} pthread_barrier_t; |
||||
|
||||
extern int pthread_barrier_init(pthread_barrier_t *barrier, |
||||
const void *attr, |
||||
int count); |
||||
extern int pthread_barrier_wait(pthread_barrier_t *barrier); |
||||
extern int pthread_barrier_destroy(pthread_barrier_t *barrier); |
||||
|
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,79 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* pthread_barrier_wait.c |
||||
* Implementation of pthread_barrier_t support for platforms lacking it. |
||||
* |
||||
* Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group |
||||
* |
||||
* IDENTIFICATION |
||||
* src/port/pthread_barrier_wait.c |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "c.h" |
||||
|
||||
#include "port/pg_pthread.h" |
||||
|
||||
int |
||||
pthread_barrier_init(pthread_barrier_t *barrier, const void *attr, int count) |
||||
{ |
||||
barrier->sense = false; |
||||
barrier->count = count; |
||||
barrier->arrived = 0; |
||||
if (pthread_cond_init(&barrier->cond, NULL) < 0) |
||||
return -1; |
||||
if (pthread_mutex_init(&barrier->mutex, NULL) < 0) |
||||
{ |
||||
int save_errno = errno; |
||||
|
||||
pthread_cond_destroy(&barrier->cond); |
||||
errno = save_errno; |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int |
||||
pthread_barrier_wait(pthread_barrier_t *barrier) |
||||
{ |
||||
bool initial_sense; |
||||
|
||||
pthread_mutex_lock(&barrier->mutex); |
||||
|
||||
/* We have arrived at the barrier. */ |
||||
barrier->arrived++; |
||||
Assert(barrier->arrived <= barrier->count); |
||||
|
||||
/* If we were the last to arrive, release the others and return. */ |
||||
if (barrier->arrived == barrier->count) |
||||
{ |
||||
barrier->arrived = 0; |
||||
barrier->sense = !barrier->sense; |
||||
pthread_mutex_unlock(&barrier->mutex); |
||||
pthread_cond_broadcast(&barrier->cond); |
||||
|
||||
return PTHREAD_BARRIER_SERIAL_THREAD; |
||||
} |
||||
|
||||
/* Wait for someone else to flip the sense. */ |
||||
initial_sense = barrier->sense; |
||||
do |
||||
{ |
||||
pthread_cond_wait(&barrier->cond, &barrier->mutex); |
||||
} while (barrier->sense == initial_sense); |
||||
|
||||
pthread_mutex_unlock(&barrier->mutex); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int |
||||
pthread_barrier_destroy(pthread_barrier_t *barrier) |
||||
{ |
||||
pthread_cond_destroy(&barrier->cond); |
||||
pthread_mutex_destroy(&barrier->mutex); |
||||
return 0; |
||||
} |
Loading…
Reference in new issue