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