summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Munro2021-03-01 03:26:22 +0000
committerThomas Munro2021-03-01 04:23:43 +0000
commit814f1d8bc395bb9b4c0ae090ceea60adfbeb8e49 (patch)
treebc3b72c9dfc433c280bf83f2670aab83fb364c7c /src
parent8bdb1332eb51837c15a10a972c179b84f654279e (diff)
Use condition variables for ProcSignalBarriers.
Instead of a poll/sleep loop, use a condition variable for precise wake-up whenever a backend's pss_barrierGeneration advances. Discussion: https://postgr.es/m/CA+hUKGLdemy2gBm80kz20GTe6hNVwoErE8KwcJk6-U56oStjtg@mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/storage/ipc/procsignal.c34
1 files changed, 14 insertions, 20 deletions
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
index ed97f4a3e97..8e5ee49fbd7 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -23,6 +23,7 @@
#include "miscadmin.h"
#include "pgstat.h"
#include "replication/walsender.h"
+#include "storage/condition_variable.h"
#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/proc.h"
@@ -59,10 +60,11 @@
*/
typedef struct
{
- pid_t pss_pid;
- sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS];
+ volatile pid_t pss_pid;
+ volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS];
pg_atomic_uint64 pss_barrierGeneration;
pg_atomic_uint32 pss_barrierCheckMask;
+ ConditionVariable pss_barrierCV;
} ProcSignalSlot;
/*
@@ -93,7 +95,7 @@ typedef struct
((flags) &= ~(((uint32) 1) << (uint32) (type)))
static ProcSignalHeader *ProcSignal = NULL;
-static volatile ProcSignalSlot *MyProcSignalSlot = NULL;
+static ProcSignalSlot *MyProcSignalSlot = NULL;
static bool CheckProcSignal(ProcSignalReason reason);
static void CleanupProcSignalState(int status, Datum arg);
@@ -142,6 +144,7 @@ ProcSignalShmemInit(void)
MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
pg_atomic_init_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX);
pg_atomic_init_u32(&slot->pss_barrierCheckMask, 0);
+ ConditionVariableInit(&slot->pss_barrierCV);
}
}
}
@@ -156,7 +159,7 @@ ProcSignalShmemInit(void)
void
ProcSignalInit(int pss_idx)
{
- volatile ProcSignalSlot *slot;
+ ProcSignalSlot *slot;
uint64 barrier_generation;
Assert(pss_idx >= 1 && pss_idx <= NumProcSignalSlots);
@@ -208,7 +211,7 @@ static void
CleanupProcSignalState(int status, Datum arg)
{
int pss_idx = DatumGetInt32(arg);
- volatile ProcSignalSlot *slot;
+ ProcSignalSlot *slot;
slot = &ProcSignal->psh_slot[pss_idx - 1];
Assert(slot == MyProcSignalSlot);
@@ -237,6 +240,7 @@ CleanupProcSignalState(int status, Datum arg)
* no barrier waits block on it.
*/
pg_atomic_write_u64(&slot->pss_barrierGeneration, PG_UINT64_MAX);
+ ConditionVariableBroadcast(&slot->pss_barrierCV);
slot->pss_pid = 0;
}
@@ -391,13 +395,11 @@ EmitProcSignalBarrier(ProcSignalBarrierType type)
void
WaitForProcSignalBarrier(uint64 generation)
{
- long timeout = 125L;
-
Assert(generation <= pg_atomic_read_u64(&ProcSignal->psh_barrierGeneration));
for (int i = NumProcSignalSlots - 1; i >= 0; i--)
{
- volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
+ ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
uint64 oldval;
/*
@@ -409,20 +411,11 @@ WaitForProcSignalBarrier(uint64 generation)
oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
while (oldval < generation)
{
- int events;
-
- CHECK_FOR_INTERRUPTS();
-
- events =
- WaitLatch(MyLatch,
- WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
- timeout, WAIT_EVENT_PROC_SIGNAL_BARRIER);
- ResetLatch(MyLatch);
-
+ ConditionVariableSleep(&slot->pss_barrierCV,
+ WAIT_EVENT_PROC_SIGNAL_BARRIER);
oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
- if (events & WL_TIMEOUT)
- timeout = Min(timeout * 2, 1000L);
}
+ ConditionVariableCancelSleep();
}
/*
@@ -589,6 +582,7 @@ ProcessProcSignalBarrier(void)
* next called.
*/
pg_atomic_write_u64(&MyProcSignalSlot->pss_barrierGeneration, shared_gen);
+ ConditionVariableBroadcast(&MyProcSignalSlot->pss_barrierCV);
}
/*