Commit 16a4e4ae authored by Robert Haas's avatar Robert Haas

Extend the ProcSignal mechanism to support barriers.

A new function EmitProcSignalBarrier() can be used to emit a global
barrier which all backends that participate in the ProcSignal
mechanism must absorb, and a new function WaitForProcSignalBarrier()
can be used to wait until all relevant backends have in fact
absorbed the barrier.

This can be used to coordinate global state changes, such as turning
checksums on while the system is running.

There's no real client of this mechanism yet, although two are
proposed, but an enum has to have at least one element, so this
includes a placeholder type (PROCSIGNAL_BARRIER_PLACEHOLDER) which
should be replaced by the first real client of this mechanism to
get committed.

Andres Freund and Robert Haas, reviewed by Daniel Gustafsson and,
in earlier versions, by Magnus Hagander.

Discussion: http://postgr.es/m/CA+TgmoZwDk=BguVDVa+qdA6SBKef=PKbaKDQALTC_9qoz1mJqg@mail.gmail.com
parent 9f83468b
......@@ -1473,7 +1473,7 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<entry>Waiting to apply WAL at recovery because it is delayed.</entry>
</row>
<row>
<entry morerows="66"><literal>IO</literal></entry>
<entry morerows="67"><literal>IO</literal></entry>
<entry><literal>BufFileRead</literal></entry>
<entry>Waiting for a read from a buffered file.</entry>
</row>
......@@ -1593,6 +1593,10 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<entry><literal>LogicalRewriteWrite</literal></entry>
<entry>Waiting for a write of logical rewrite mappings.</entry>
</row>
<row>
<entry><literal>ProcSignalBarrier</literal></entry>
<entry>Waiting for a barrier event to be processed by all backends.</entry>
</row>
<row>
<entry><literal>RelationMapRead</literal></entry>
<entry>Waiting for a read of the relation map file.</entry>
......
......@@ -820,6 +820,10 @@ HandleAutoVacLauncherInterrupts(void)
rebuild_database_list(InvalidOid);
}
/* Process barrier events */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
/* Process sinval catchup interrupts that happened while sleeping */
ProcessCatchupInterrupt();
}
......
......@@ -524,6 +524,9 @@ CheckpointerMain(void)
static void
HandleCheckpointerInterrupts(void)
{
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
if (ConfigReloadPending)
{
ConfigReloadPending = false;
......@@ -710,6 +713,10 @@ CheckpointWriteDelay(int flags, double progress)
AbsorbSyncRequests();
absorb_counter = WRITES_PER_ABSORB;
}
/* Check for barrier events. */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
}
/*
......
......@@ -20,6 +20,7 @@
#include "postmaster/interrupt.h"
#include "storage/ipc.h"
#include "storage/latch.h"
#include "storage/procsignal.h"
#include "utils/guc.h"
volatile sig_atomic_t ConfigReloadPending = false;
......@@ -31,6 +32,9 @@ volatile sig_atomic_t ShutdownRequestPending = false;
void
HandleMainLoopInterrupts(void)
{
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
if (ConfigReloadPending)
{
ConfigReloadPending = false;
......
......@@ -3988,6 +3988,9 @@ pgstat_get_wait_io(WaitEventIO w)
case WAIT_EVENT_LOGICAL_REWRITE_WRITE:
event_name = "LogicalRewriteWrite";
break;
case WAIT_EVENT_PROC_SIGNAL_BARRIER:
event_name = "ProcSignalBarrier";
break;
case WAIT_EVENT_RELATION_MAP_READ:
event_name = "RelationMapRead";
break;
......
......@@ -96,7 +96,7 @@ StartupProcShutdownHandler(SIGNAL_ARGS)
errno = save_errno;
}
/* Handle SIGHUP and SIGTERM signals of startup process */
/* Handle various signals that might be sent to the startup process */
void
HandleStartupProcInterrupts(void)
{
......@@ -121,6 +121,10 @@ HandleStartupProcInterrupts(void)
*/
if (IsUnderPostmaster && !PostmasterIsAlive())
exit(1);
/* Process barrier events */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
}
......
......@@ -148,7 +148,8 @@ ProcessWalRcvInterrupts(void)
/*
* Although walreceiver interrupt handling doesn't use the same scheme as
* regular backends, call CHECK_FOR_INTERRUPTS() to make sure we receive
* any incoming signals on Win32.
* any incoming signals on Win32, and also to make sure we process any
* barrier events.
*/
CHECK_FOR_INTERRUPTS();
......
......@@ -1852,6 +1852,10 @@ BufferSync(int flags)
}
UnlockBufHdr(bufHdr, buf_state);
/* Check for barrier events in case NBuffers is large. */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
}
if (num_to_scan == 0)
......@@ -1930,6 +1934,10 @@ BufferSync(int flags)
}
s->num_to_scan++;
/* Check for barrier events. */
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
}
Assert(num_spaces > 0);
......@@ -2018,6 +2026,8 @@ BufferSync(int flags)
/*
* Sleep to throttle our I/O rate.
*
* (This will check for barrier events even if it doesn't sleep.)
*/
CheckpointWriteDelay(flags, (double) num_processed / num_to_scan);
}
......
This diff is collapsed.
......@@ -3180,6 +3180,9 @@ ProcessInterrupts(void)
}
if (ProcSignalBarrierPending)
ProcessProcSignalBarrier();
if (ParallelMessagePending)
HandleParallelMessages();
}
......
......@@ -32,6 +32,7 @@ volatile sig_atomic_t QueryCancelPending = false;
volatile sig_atomic_t ProcDiePending = false;
volatile sig_atomic_t ClientConnectionLost = false;
volatile sig_atomic_t IdleInTransactionSessionTimeoutPending = false;
volatile sig_atomic_t ProcSignalBarrierPending = false;
volatile uint32 InterruptHoldoffCount = 0;
volatile uint32 QueryCancelHoldoffCount = 0;
volatile uint32 CritSectionCount = 0;
......
......@@ -82,6 +82,7 @@ extern PGDLLIMPORT volatile sig_atomic_t InterruptPending;
extern PGDLLIMPORT volatile sig_atomic_t QueryCancelPending;
extern PGDLLIMPORT volatile sig_atomic_t ProcDiePending;
extern PGDLLIMPORT volatile sig_atomic_t IdleInTransactionSessionTimeoutPending;
extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending;
extern PGDLLIMPORT volatile sig_atomic_t ClientConnectionLost;
......
......@@ -908,6 +908,7 @@ typedef enum
WAIT_EVENT_LOGICAL_REWRITE_SYNC,
WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
WAIT_EVENT_LOGICAL_REWRITE_WRITE,
WAIT_EVENT_PROC_SIGNAL_BARRIER,
WAIT_EVENT_RELATION_MAP_READ,
WAIT_EVENT_RELATION_MAP_SYNC,
WAIT_EVENT_RELATION_MAP_WRITE,
......
......@@ -45,6 +45,16 @@ typedef enum
NUM_PROCSIGNALS /* Must be last! */
} ProcSignalReason;
typedef enum
{
/*
* XXX. PROCSIGNAL_BARRIER_PLACEHOLDER should be replaced when the first
* real user of the ProcSignalBarrier mechanism is added. It's just here
* for now because we can't have an empty enum.
*/
PROCSIGNAL_BARRIER_PLACEHOLDER = 0
} ProcSignalBarrierType;
/*
* prototypes for functions in procsignal.c
*/
......@@ -55,6 +65,10 @@ extern void ProcSignalInit(int pss_idx);
extern int SendProcSignal(pid_t pid, ProcSignalReason reason,
BackendId backendId);
extern uint64 EmitProcSignalBarrier(ProcSignalBarrierType type);
extern void WaitForProcSignalBarrier(uint64 generation);
extern void ProcessProcSignalBarrier(void);
extern void procsignal_sigusr1_handler(SIGNAL_ARGS);
#endif /* PROCSIGNAL_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment