Add BarrierArriveAndDetachExceptLast().
authorThomas Munro <tmunro@postgresql.org>
Thu, 19 Nov 2020 05:09:50 +0000 (18:09 +1300)
committerThomas Munro <tmunro@postgresql.org>
Thu, 19 Nov 2020 05:13:46 +0000 (18:13 +1300)
Provide a way for one process to continue the remaining phases of a
(previously) parallel computation alone.  Later patches will use this to
extend Parallel Hash Join.

Author: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Thomas Munro <thomas.munro@gmail.com>
Discussion: https://postgr.es/m/CA%2BhUKG%2BA6ftXPz4oe92%2Bx8Er%2BxpGZqto70-Q_ERwRaSyA%3DafNg%40mail.gmail.com

src/backend/storage/ipc/barrier.c
src/include/storage/barrier.h

index 3e200e02cc225e2a8a805ac282d4577d14939106..69afd586898851f331e56f4cd5ffd5bb063fc31c 100644 (file)
@@ -205,6 +205,28 @@ BarrierArriveAndDetach(Barrier *barrier)
    return BarrierDetachImpl(barrier, true);
 }
 
+/*
+ * Arrive at a barrier, and detach all but the last to arrive.  Returns true if
+ * the caller was the last to arrive, and is therefore still attached.
+ */
+bool
+BarrierArriveAndDetachExceptLast(Barrier *barrier)
+{
+   SpinLockAcquire(&barrier->mutex);
+   if (barrier->participants > 1)
+   {
+       --barrier->participants;
+       SpinLockRelease(&barrier->mutex);
+
+       return false;
+   }
+   Assert(barrier->participants == 1);
+   ++barrier->phase;
+   SpinLockRelease(&barrier->mutex);
+
+   return true;
+}
+
 /*
  * Attach to a barrier.  All waiting participants will now wait for this
  * participant to call BarrierArriveAndWait(), BarrierDetach() or
index d71927cc2f7a8cb33bde2df7db770324c9d5b4f0..e0de24378bff967af3c3f7121e7acbb1b3dd9ead 100644 (file)
@@ -37,6 +37,7 @@ typedef struct Barrier
 extern void BarrierInit(Barrier *barrier, int num_workers);
 extern bool BarrierArriveAndWait(Barrier *barrier, uint32 wait_event_info);
 extern bool BarrierArriveAndDetach(Barrier *barrier);
+extern bool BarrierArriveAndDetachExceptLast(Barrier *barrier);
 extern int BarrierAttach(Barrier *barrier);
 extern bool BarrierDetach(Barrier *barrier);
 extern int BarrierPhase(Barrier *barrier);