0002-Add-pthread_barrier_t-emulation.patch
application/octet-stream
Filename: 0002-Add-pthread_barrier_t-emulation.patch
Type: application/octet-stream
Part: 1
Patch
Format: format-patch
Series: patch 0002
Subject: Add pthread_barrier_t emulation.
| File | + | − |
|---|---|---|
| configure | 69 | 0 |
| configure.ac | 2 | 0 |
| src/include/pg_config.h.in | 3 | 0 |
| src/include/port/pg_pthread.h | 40 | 0 |
| src/port/pthread_barrier_wait.c | 64 | 0 |
From 612e7c2a873a11103801c24ce2c8361afa1fa195 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 2 Jan 2021 15:05:06 +1300
Subject: [PATCH 2/3] Add pthread_barrier_t emulation.
Map pthread_barrier_t to native barriers on Windows. Supply an
implementation based on other pthread primitives for macOS.
Discussion: https://postgr.es/m/20200227180100.zyvjwzcpiokfsqm2%40alap3.anarazel.de
---
configure | 69 +++++++++++++++++++++++++++++++++
configure.ac | 2 +
src/include/pg_config.h.in | 3 ++
src/include/port/pg_pthread.h | 40 +++++++++++++++++++
src/port/pthread_barrier_wait.c | 64 ++++++++++++++++++++++++++++++
5 files changed, 178 insertions(+)
create mode 100644 src/include/port/pg_pthread.h
create mode 100644 src/port/pthread_barrier_wait.c
diff --git a/configure b/configure
index 07529825d1..5a749b66da 100755
--- a/configure
+++ b/configure
@@ -11673,6 +11673,62 @@ if test "$ac_res" != no; then :
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing pthread_barrier_wait" >&5
+$as_echo_n "checking for library containing pthread_barrier_wait... " >&6; }
+if ${ac_cv_search_pthread_barrier_wait+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_barrier_wait ();
+int
+main ()
+{
+return pthread_barrier_wait ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_pthread_barrier_wait=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_pthread_barrier_wait+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_pthread_barrier_wait+:} false; then :
+
+else
+ ac_cv_search_pthread_barrier_wait=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_pthread_barrier_wait" >&5
+$as_echo "$ac_cv_search_pthread_barrier_wait" >&6; }
+ac_res=$ac_cv_search_pthread_barrier_wait
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
# Solaris:
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5
$as_echo_n "checking for library containing fdatasync... " >&6; }
@@ -15845,6 +15901,19 @@ esac
fi
+ac_fn_c_check_func "$LINENO" "pthread_barrier_wait" "ac_cv_func_pthread_barrier_wait"
+if test "x$ac_cv_func_pthread_barrier_wait" = xyes; then :
+ $as_echo "#define HAVE_PTHREAD_BARRIER_WAIT 1" >>confdefs.h
+
+else
+ case " $LIBOBJS " in
+ *" pthread_barrier_wait.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS pthread_barrier_wait.$ac_objext"
+ ;;
+esac
+
+fi
+
ac_fn_c_check_func "$LINENO" "pwrite" "ac_cv_func_pwrite"
if test "x$ac_cv_func_pwrite" = xyes; then :
$as_echo "#define HAVE_PWRITE 1" >>confdefs.h
diff --git a/configure.ac b/configure.ac
index 7f855783f4..1d3cc1751c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1156,6 +1156,7 @@ AC_SEARCH_LIBS(getopt_long, [getopt gnugetopt])
AC_SEARCH_LIBS(shm_open, rt)
AC_SEARCH_LIBS(shm_unlink, rt)
AC_SEARCH_LIBS(clock_gettime, [rt posix4])
+AC_SEARCH_LIBS(pthread_barrier_wait, pthread)
# Solaris:
AC_SEARCH_LIBS(fdatasync, [rt posix4])
# Required for thread_test.c on Solaris
@@ -1734,6 +1735,7 @@ AC_REPLACE_FUNCS(m4_normalize([
link
mkdtemp
pread
+ pthread_barrier_wait
pwrite
random
srandom
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index ddaa9e8e18..b9f828385c 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -421,6 +421,9 @@
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
+/* Define to 1 if you have the `pthread_barrier_wait' function. */
+#undef HAVE_PTHREAD_BARRIER_WAIT
+
/* Define to 1 if you have the `pthread_is_threaded_np' function. */
#undef HAVE_PTHREAD_IS_THREADED_NP
diff --git a/src/include/port/pg_pthread.h b/src/include/port/pg_pthread.h
new file mode 100644
index 0000000000..21987429eb
--- /dev/null
+++ b/src/include/port/pg_pthread.h
@@ -0,0 +1,40 @@
+#ifndef PG_PTHREAD_H
+#define PG_PTHREAD_H
+
+#ifndef WIN32
+#include <pthread.h>
+#endif
+
+#ifndef HAVE_PTHREAD_BARRIER_WAIT
+
+#ifndef PTHREAD_BARRIER_SERIAL_THREAD
+#define PTHREAD_BARRIER_SERIAL_THREAD (-1)
+#endif
+
+#ifdef WIN32
+/* Forward to the appropriate Win32 primitives. */
+typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
+#else
+/*
+ * For systems that have no pthread barriers, but have the rest of the pthread
+ * stuff (that's at least macOS), we'll do our own simple barrier
+ * implementation.
+ */
+typedef struct pg_pthread_barrier
+{
+ bool sense; /* we only need a one bit phase */
+ int party; /* number of threads expected */
+ int arrived; /* number of threads that have arrived */
+ pthread_mutex_t mutex;
+ pthread_cond_t cv;
+} pthread_barrier_t;
+#endif
+
+extern int pthread_barrier_init(pthread_barrier_t *barrier, void *unused,
+ int party);
+extern int pthread_barrier_wait(pthread_barrier_t *barrier);
+extern int pthread_barrier_destroy(pthread_barrier_t *barrier);
+
+#endif
+
+#endif
diff --git a/src/port/pthread_barrier_wait.c b/src/port/pthread_barrier_wait.c
new file mode 100644
index 0000000000..6c8a0f29a9
--- /dev/null
+++ b/src/port/pthread_barrier_wait.c
@@ -0,0 +1,64 @@
+#include "postgres_fe.h"
+
+#include "port/pg_pthread.h"
+
+int
+pthread_barrier_init(pthread_barrier_t *barrier, void *unused, int party)
+{
+#ifdef WIN32
+ InitializeSynchronizationBarrier(barrier, party, 0);
+#else
+ barrier->sense = false;
+ barrier->party = party;
+ barrier->arrived = 0;
+ pthread_cond_init(&barrier->cv, NULL);
+ pthread_mutex_init(&barrier->mutex, NULL);
+ return 0;
+#endif
+}
+
+int
+pthread_barrier_wait(pthread_barrier_t *barrier)
+{
+#ifdef WIN32
+ if (EnterSynchronizationBarrier(barrier,
+ SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY))
+ return PTHREAD_BARRIER_SERIAL_THREAD;
+#else
+ bool initial_sense;
+
+ pthread_mutex_lock(&barrier->mutex);
+
+ /* We have arrived at the barrier. */
+ barrier->arrived++;
+ Assert(barrier->arrived <= barrier->party);
+
+ /* If we were the last to arrive, release the others and return. */
+ if (barrier->arrived == barrier->party)
+ {
+ barrier->arrived = 0;
+ barrier->sense = !barrier->sense;
+ pthread_mutex_unlock(&barrier->mutex);
+ pthread_cond_broadcast(&barrier->cv);
+
+ return PTHREAD_BARRIER_SERIAL_THREAD;
+ }
+
+ /* Wait for someone else to flip the sense. */
+ initial_sense = barrier->sense;
+ do
+ {
+ pthread_cond_wait(&barrier->cv, &barrier->mutex);
+ } while (barrier->sense == initial_sense);
+ pthread_mutex_unlock(&barrier->mutex);
+#endif
+
+ return 0;
+}
+
+int
+pthread_barrier_destroy(pthread_barrier_t *barrier)
+{
+ /* XXX DeleteSynchronizationBarrier() in Windows 8, Windows Server 2012? */
+ return 0;
+}
--
2.24.3 (Apple Git-128)