PostgreSQL Source Code  git master
procsignal.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include "access/parallel.h"
#include "port/pg_bitutils.h"
#include "commands/async.h"
#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"
#include "storage/shmem.h"
#include "storage/sinval.h"
#include "tcop/tcopprot.h"
#include "utils/memutils.h"
Include dependency graph for procsignal.c:

Go to the source code of this file.

Data Structures

struct  ProcSignalSlot
 
struct  ProcSignalHeader
 

Macros

#define NumProcSignalSlots   (MaxBackends + NUM_AUXPROCTYPES)
 
#define BARRIER_SHOULD_CHECK(flags, type)   (((flags) & (((uint32) 1) << (uint32) (type))) != 0)
 
#define BARRIER_CLEAR_BIT(flags, type)   ((flags) &= ~(((uint32) 1) << (uint32) (type)))
 

Functions

static bool CheckProcSignal (ProcSignalReason reason)
 
static void CleanupProcSignalState (int status, Datum arg)
 
static void ResetProcSignalBarrierBits (uint32 flags)
 
static bool ProcessBarrierPlaceholder (void)
 
Size ProcSignalShmemSize (void)
 
void ProcSignalShmemInit (void)
 
void ProcSignalInit (int pss_idx)
 
int SendProcSignal (pid_t pid, ProcSignalReason reason, BackendId backendId)
 
uint64 EmitProcSignalBarrier (ProcSignalBarrierType type)
 
void WaitForProcSignalBarrier (uint64 generation)
 
static void HandleProcSignalBarrierInterrupt (void)
 
void ProcessProcSignalBarrier (void)
 
void procsignal_sigusr1_handler (SIGNAL_ARGS)
 

Variables

static ProcSignalHeaderProcSignal = NULL
 
static ProcSignalSlotMyProcSignalSlot = NULL
 

Macro Definition Documentation

◆ BARRIER_CLEAR_BIT

#define BARRIER_CLEAR_BIT (   flags,
  type 
)    ((flags) &= ~(((uint32) 1) << (uint32) (type)))

Definition at line 95 of file procsignal.c.

Referenced by ProcessProcSignalBarrier().

◆ BARRIER_SHOULD_CHECK

#define BARRIER_SHOULD_CHECK (   flags,
  type 
)    (((flags) & (((uint32) 1) << (uint32) (type))) != 0)

Definition at line 91 of file procsignal.c.

◆ NumProcSignalSlots

Function Documentation

◆ CheckProcSignal()

static bool CheckProcSignal ( ProcSignalReason  reason)
static

Definition at line 621 of file procsignal.c.

References MyProcSignalSlot, and ProcSignalSlot::pss_signalFlags.

Referenced by procsignal_sigusr1_handler().

622 {
623  volatile ProcSignalSlot *slot = MyProcSignalSlot;
624 
625  if (slot != NULL)
626  {
627  /* Careful here --- don't clear flag if we haven't seen it set */
628  if (slot->pss_signalFlags[reason])
629  {
630  slot->pss_signalFlags[reason] = false;
631  return true;
632  }
633  }
634 
635  return false;
636 }
volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:65
static ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:99

◆ CleanupProcSignalState()

static void CleanupProcSignalState ( int  status,
Datum  arg 
)
static

Definition at line 212 of file procsignal.c.

References Assert, ConditionVariableBroadcast(), DatumGetInt32, elog, LOG, MyProcPid, pg_atomic_write_u64(), PG_UINT64_MAX, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, and ProcSignalSlot::pss_pid.

Referenced by ProcSignalInit().

213 {
214  int pss_idx = DatumGetInt32(arg);
215  ProcSignalSlot *slot;
216 
217  slot = &ProcSignal->psh_slot[pss_idx - 1];
218  Assert(slot == MyProcSignalSlot);
219 
220  /*
221  * Clear MyProcSignalSlot, so that a SIGUSR1 received after this point
222  * won't try to access it after it's no longer ours (and perhaps even
223  * after we've unmapped the shared memory segment).
224  */
225  MyProcSignalSlot = NULL;
226 
227  /* sanity check */
228  if (slot->pss_pid != MyProcPid)
229  {
230  /*
231  * don't ERROR here. We're exiting anyway, and don't want to get into
232  * infinite loop trying to exit
233  */
234  elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d",
235  MyProcPid, pss_idx, (int) slot->pss_pid);
236  return; /* XXX better to zero the slot anyway? */
237  }
238 
239  /*
240  * Make this slot look like it's absorbed all possible barriers, so that
241  * no barrier waits block on it.
242  */
245 
246  slot->pss_pid = 0;
247 }
int MyProcPid
Definition: globals.c:43
#define PG_UINT64_MAX
Definition: c.h:528
#define DatumGetInt32(X)
Definition: postgres.h:516
void ConditionVariableBroadcast(ConditionVariable *cv)
#define LOG
Definition: elog.h:26
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:66
static ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:99
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:438
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:80
volatile pid_t pss_pid
Definition: procsignal.c:64
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
#define Assert(condition)
Definition: c.h:804
#define elog(elevel,...)
Definition: elog.h:232
void * arg
ConditionVariable pss_barrierCV
Definition: procsignal.c:68

◆ EmitProcSignalBarrier()

uint64 EmitProcSignalBarrier ( ProcSignalBarrierType  type)

Definition at line 332 of file procsignal.c.

References i, kill, NumProcSignalSlots, pg_atomic_add_fetch_u64(), pg_atomic_fetch_or_u32(), PROCSIG_BARRIER, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, and SIGUSR1.

333 {
334  uint32 flagbit = 1 << (uint32) type;
335  uint64 generation;
336 
337  /*
338  * Set all the flags.
339  *
340  * Note that pg_atomic_fetch_or_u32 has full barrier semantics, so this is
341  * totally ordered with respect to anything the caller did before, and
342  * anything that we do afterwards. (This is also true of the later call to
343  * pg_atomic_add_fetch_u64.)
344  */
345  for (int i = 0; i < NumProcSignalSlots; i++)
346  {
347  volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
348 
350  }
351 
352  /*
353  * Increment the generation counter.
354  */
355  generation =
357 
358  /*
359  * Signal all the processes, so that they update their advertised barrier
360  * generation.
361  *
362  * Concurrency is not a problem here. Backends that have exited don't
363  * matter, and new backends that have joined since we entered this
364  * function must already have current state, since the caller is
365  * responsible for making sure that the relevant state is entirely visible
366  * before calling this function in the first place. We still have to wake
367  * them up - because we can't distinguish between such backends and older
368  * backends that need to update state - but they won't actually need to
369  * change any state.
370  */
371  for (int i = NumProcSignalSlots - 1; i >= 0; i--)
372  {
373  volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
374  pid_t pid = slot->pss_pid;
375 
376  if (pid != 0)
377  {
378  /* see SendProcSignal for details */
379  slot->pss_signalFlags[PROCSIG_BARRIER] = true;
380  kill(pid, SIGUSR1);
381  }
382  }
383 
384  return generation;
385 }
volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:65
#define SIGUSR1
Definition: win32_port.h:179
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:79
#define kill(pid, sig)
Definition: win32_port.h:464
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:80
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:67
unsigned int uint32
Definition: c.h:441
volatile pid_t pss_pid
Definition: procsignal.c:64
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
static uint64 pg_atomic_add_fetch_u64(volatile pg_atomic_uint64 *ptr, int64 add_)
Definition: atomics.h:504
int i
#define NumProcSignalSlots
Definition: procsignal.c:88
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition: atomics.h:372

◆ HandleProcSignalBarrierInterrupt()

static void HandleProcSignalBarrierInterrupt ( void  )
static

Definition at line 437 of file procsignal.c.

References InterruptPending, and ProcSignalBarrierPending.

Referenced by procsignal_sigusr1_handler().

438 {
439  InterruptPending = true;
441  /* latch will be set by procsignal_sigusr1_handler */
442 }
volatile sig_atomic_t ProcSignalBarrierPending
Definition: globals.c:37
volatile sig_atomic_t InterruptPending
Definition: globals.c:30

◆ ProcessBarrierPlaceholder()

static bool ProcessBarrierPlaceholder ( void  )
static

Definition at line 598 of file procsignal.c.

Referenced by ProcessProcSignalBarrier().

599 {
600  /*
601  * XXX. This is just a placeholder until the first real user of this
602  * machinery gets committed. Rename PROCSIGNAL_BARRIER_PLACEHOLDER to
603  * PROCSIGNAL_BARRIER_SOMETHING_ELSE where SOMETHING_ELSE is something
604  * appropriately descriptive. Get rid of this function and instead have
605  * ProcessBarrierSomethingElse. Most likely, that function should live in
606  * the file pertaining to that subsystem, rather than here.
607  *
608  * The return value should be 'true' if the barrier was successfully
609  * absorbed and 'false' if not. Note that returning 'false' can lead to
610  * very frequent retries, so try hard to make that an uncommon case.
611  */
612  return true;
613 }

◆ ProcessProcSignalBarrier()

void ProcessProcSignalBarrier ( void  )

Definition at line 453 of file procsignal.c.

References Assert, BARRIER_CLEAR_BIT, ConditionVariableBroadcast(), pg_atomic_exchange_u32(), pg_atomic_read_u64(), pg_atomic_write_u64(), PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_rightmost_one_pos32(), PG_TRY, ProcessBarrierPlaceholder(), PROCSIGNAL_BARRIER_PLACEHOLDER, ProcSignalBarrierPending, ProcSignalHeader::psh_barrierGeneration, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, ResetProcSignalBarrierBits(), success, and generate_unaccent_rules::type.

Referenced by BufferSync(), CheckpointWriteDelay(), HandleAutoVacLauncherInterrupts(), HandleCheckpointerInterrupts(), HandleMainLoopInterrupts(), HandlePgArchInterrupts(), HandleStartupProcInterrupts(), HandleWalWriterInterrupts(), and ProcessInterrupts().

454 {
455  uint64 local_gen;
456  uint64 shared_gen;
457  volatile uint32 flags;
458 
460 
461  /* Exit quickly if there's no work to do. */
463  return;
464  ProcSignalBarrierPending = false;
465 
466  /*
467  * It's not unlikely to process multiple barriers at once, before the
468  * signals for all the barriers have arrived. To avoid unnecessary work in
469  * response to subsequent signals, exit early if we already have processed
470  * all of them.
471  */
474 
475  Assert(local_gen <= shared_gen);
476 
477  if (local_gen == shared_gen)
478  return;
479 
480  /*
481  * Get and clear the flags that are set for this backend. Note that
482  * pg_atomic_exchange_u32 is a full barrier, so we're guaranteed that the
483  * read of the barrier generation above happens before we atomically
484  * extract the flags, and that any subsequent state changes happen
485  * afterward.
486  *
487  * NB: In order to avoid race conditions, we must zero
488  * pss_barrierCheckMask first and only afterwards try to do barrier
489  * processing. If we did it in the other order, someone could send us
490  * another barrier of some type right after we called the
491  * barrier-processing function but before we cleared the bit. We would
492  * have no way of knowing that the bit needs to stay set in that case, so
493  * the need to call the barrier-processing function again would just get
494  * forgotten. So instead, we tentatively clear all the bits and then put
495  * back any for which we don't manage to successfully absorb the barrier.
496  */
498 
499  /*
500  * If there are no flags set, then we can skip doing any real work.
501  * Otherwise, establish a PG_TRY block, so that we don't lose track of
502  * which types of barrier processing are needed if an ERROR occurs.
503  */
504  if (flags != 0)
505  {
506  bool success = true;
507 
508  PG_TRY();
509  {
510  /*
511  * Process each type of barrier. The barrier-processing functions
512  * should normally return true, but may return false if the
513  * barrier can't be absorbed at the current time. This should be
514  * rare, because it's pretty expensive. Every single
515  * CHECK_FOR_INTERRUPTS() will return here until we manage to
516  * absorb the barrier, and that cost will add up in a hurry.
517  *
518  * NB: It ought to be OK to call the barrier-processing functions
519  * unconditionally, but it's more efficient to call only the ones
520  * that might need us to do something based on the flags.
521  */
522  while (flags != 0)
523  {
525  bool processed = true;
526 
528  switch (type)
529  {
531  processed = ProcessBarrierPlaceholder();
532  break;
533  }
534 
535  /*
536  * To avoid an infinite loop, we must always unset the bit in
537  * flags.
538  */
539  BARRIER_CLEAR_BIT(flags, type);
540 
541  /*
542  * If we failed to process the barrier, reset the shared bit
543  * so we try again later, and set a flag so that we don't bump
544  * our generation.
545  */
546  if (!processed)
547  {
548  ResetProcSignalBarrierBits(((uint32) 1) << type);
549  success = false;
550  }
551  }
552  }
553  PG_CATCH();
554  {
555  /*
556  * If an ERROR occurred, we'll need to try again later to handle
557  * that barrier type and any others that haven't been handled yet
558  * or weren't successfully absorbed.
559  */
561  PG_RE_THROW();
562  }
563  PG_END_TRY();
564 
565  /*
566  * If some barrier types were not successfully absorbed, we will have
567  * to try again later.
568  */
569  if (!success)
570  return;
571  }
572 
573  /*
574  * State changes related to all types of barriers that might have been
575  * emitted have now been handled, so we can update our notion of the
576  * generation to the one we observed before beginning the updates. If
577  * things have changed further, it'll get fixed up when this function is
578  * next called.
579  */
582 }
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:79
void ConditionVariableBroadcast(ConditionVariable *cv)
static bool ProcessBarrierPlaceholder(void)
Definition: procsignal.c:598
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:66
static ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:99
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:438
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:292
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:67
unsigned int uint32
Definition: c.h:441
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
#define BARRIER_CLEAR_BIT(flags, type)
Definition: procsignal.c:95
#define PG_CATCH()
Definition: elog.h:323
#define Assert(condition)
Definition: c.h:804
volatile sig_atomic_t ProcSignalBarrierPending
Definition: globals.c:37
static void ResetProcSignalBarrierBits(uint32 flags)
Definition: procsignal.c:590
#define PG_RE_THROW()
Definition: elog.h:354
ProcSignalBarrierType
Definition: procsignal.h:50
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:429
#define PG_TRY()
Definition: elog.h:313
static bool success
Definition: initdb.c:165
ConditionVariable pss_barrierCV
Definition: procsignal.c:68
#define PG_END_TRY()
Definition: elog.h:338
static int pg_rightmost_one_pos32(uint32 word)
Definition: pg_bitutils.h:85

◆ procsignal_sigusr1_handler()

void procsignal_sigusr1_handler ( SIGNAL_ARGS  )

Definition at line 642 of file procsignal.c.

References CheckProcSignal(), HandleCatchupInterrupt(), HandleLogMemoryContextInterrupt(), HandleNotifyInterrupt(), HandleParallelMessageInterrupt(), HandleProcSignalBarrierInterrupt(), HandleWalSndInitStopping(), MyLatch, PROCSIG_BARRIER, PROCSIG_CATCHUP_INTERRUPT, PROCSIG_LOG_MEMORY_CONTEXT, PROCSIG_NOTIFY_INTERRUPT, PROCSIG_PARALLEL_MESSAGE, PROCSIG_RECOVERY_CONFLICT_BUFFERPIN, PROCSIG_RECOVERY_CONFLICT_DATABASE, PROCSIG_RECOVERY_CONFLICT_LOCK, PROCSIG_RECOVERY_CONFLICT_SNAPSHOT, PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK, PROCSIG_RECOVERY_CONFLICT_TABLESPACE, PROCSIG_WALSND_INIT_STOPPING, RecoveryConflictInterrupt(), and SetLatch().

Referenced by autoprewarm_main(), AutoVacLauncherMain(), AutoVacWorkerMain(), BackgroundWriterMain(), CheckpointerMain(), PgArchiverMain(), PostgresMain(), StartBackgroundWorker(), StartupProcessMain(), WalReceiverMain(), WalSndSignals(), and WalWriterMain().

643 {
644  int save_errno = errno;
645 
648 
651 
654 
657 
660 
663 
666 
669 
672 
675 
678 
681 
682  SetLatch(MyLatch);
683 
684  errno = save_errno;
685 }
void RecoveryConflictInterrupt(ProcSignalReason reason)
Definition: postgres.c:2988
static void HandleProcSignalBarrierInterrupt(void)
Definition: procsignal.c:437
void SetLatch(Latch *latch)
Definition: latch.c:567
void HandleWalSndInitStopping(void)
Definition: walsender.c:3129
static bool CheckProcSignal(ProcSignalReason reason)
Definition: procsignal.c:621
void HandleNotifyInterrupt(void)
Definition: async.c:1853
struct Latch * MyLatch
Definition: globals.c:57
void HandleParallelMessageInterrupt(void)
Definition: parallel.c:1003
void HandleLogMemoryContextInterrupt(void)
Definition: mcxt.c:1024
void HandleCatchupInterrupt(void)
Definition: sinval.c:156

◆ ProcSignalInit()

void ProcSignalInit ( int  pss_idx)

Definition at line 161 of file procsignal.c.

References Assert, CleanupProcSignalState(), elog, Int32GetDatum, LOG, MemSet, MyProcPid, NUM_PROCSIGNALS, NumProcSignalSlots, on_shmem_exit(), pg_atomic_read_u64(), pg_atomic_write_u32(), pg_atomic_write_u64(), pg_memory_barrier, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_barrierGeneration, ProcSignalSlot::pss_pid, and ProcSignalSlot::pss_signalFlags.

Referenced by AuxiliaryProcessMain(), and InitPostgres().

162 {
163  ProcSignalSlot *slot;
164  uint64 barrier_generation;
165 
166  Assert(pss_idx >= 1 && pss_idx <= NumProcSignalSlots);
167 
168  slot = &ProcSignal->psh_slot[pss_idx - 1];
169 
170  /* sanity check */
171  if (slot->pss_pid != 0)
172  elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty",
173  MyProcPid, pss_idx);
174 
175  /* Clear out any leftover signal reasons */
176  MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t));
177 
178  /*
179  * Initialize barrier state. Since we're a brand-new process, there
180  * shouldn't be any leftover backend-private state that needs to be
181  * updated. Therefore, we can broadcast the latest barrier generation and
182  * disregard any previously-set check bits.
183  *
184  * NB: This only works if this initialization happens early enough in the
185  * startup sequence that we haven't yet cached any state that might need
186  * to be invalidated. That's also why we have a memory barrier here, to be
187  * sure that any later reads of memory happen strictly after this.
188  */
190  barrier_generation =
192  pg_atomic_write_u64(&slot->pss_barrierGeneration, barrier_generation);
194 
195  /* Mark slot with my PID */
196  slot->pss_pid = MyProcPid;
197 
198  /* Remember slot location for CheckProcSignal */
199  MyProcSignalSlot = slot;
200 
201  /* Set up to release the slot on process exit */
203 }
volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:65
int MyProcPid
Definition: globals.c:43
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:79
#define MemSet(start, val, len)
Definition: c.h:1008
#define LOG
Definition: elog.h:26
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:66
static ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:99
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:438
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:80
static void CleanupProcSignalState(int status, Datum arg)
Definition: procsignal.c:212
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:67
volatile pid_t pss_pid
Definition: procsignal.c:64
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
#define pg_memory_barrier()
Definition: atomics.h:145
#define Assert(condition)
Definition: c.h:804
#define Int32GetDatum(X)
Definition: postgres.h:523
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:429
#define elog(elevel,...)
Definition: elog.h:232
#define NumProcSignalSlots
Definition: procsignal.c:88
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:258

◆ ProcSignalShmemInit()

void ProcSignalShmemInit ( void  )

Definition at line 125 of file procsignal.c.

References ConditionVariableInit(), i, MemSet, NumProcSignalSlots, pg_atomic_init_u32(), pg_atomic_init_u64(), PG_UINT64_MAX, ProcSignalShmemSize(), ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCheckMask, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, and ShmemInitStruct().

Referenced by CreateSharedMemoryAndSemaphores().

126 {
127  Size size = ProcSignalShmemSize();
128  bool found;
129 
131  ShmemInitStruct("ProcSignal", size, &found);
132 
133  /* If we're first, initialize. */
134  if (!found)
135  {
136  int i;
137 
139 
140  for (i = 0; i < NumProcSignalSlots; ++i)
141  {
142  ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
143 
144  slot->pss_pid = 0;
145  MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
149  }
150  }
151 }
volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:65
#define PG_UINT64_MAX
Definition: c.h:528
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:79
#define MemSet(start, val, len)
Definition: c.h:1008
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:66
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:80
void ConditionVariableInit(ConditionVariable *cv)
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:415
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:67
volatile pid_t pss_pid
Definition: procsignal.c:64
Size ProcSignalShmemSize(void)
Definition: procsignal.c:111
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
size_t Size
Definition: c.h:540
int i
#define NumProcSignalSlots
Definition: procsignal.c:88
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:223
ConditionVariable pss_barrierCV
Definition: procsignal.c:68

◆ ProcSignalShmemSize()

Size ProcSignalShmemSize ( void  )

Definition at line 111 of file procsignal.c.

References add_size(), mul_size(), NumProcSignalSlots, and offsetof.

Referenced by CalculateShmemSize(), and ProcSignalShmemInit().

112 {
113  Size size;
114 
115  size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot));
116  size = add_size(size, offsetof(ProcSignalHeader, psh_slot));
117  return size;
118 }
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
size_t Size
Definition: c.h:540
#define NumProcSignalSlots
Definition: procsignal.c:88
#define offsetof(type, field)
Definition: c.h:727

◆ ResetProcSignalBarrierBits()

static void ResetProcSignalBarrierBits ( uint32  flags)
static

Definition at line 590 of file procsignal.c.

References InterruptPending, pg_atomic_fetch_or_u32(), ProcSignalBarrierPending, and ProcSignalSlot::pss_barrierCheckMask.

Referenced by ProcessProcSignalBarrier().

591 {
594  InterruptPending = true;
595 }
static ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:99
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:67
volatile sig_atomic_t ProcSignalBarrierPending
Definition: globals.c:37
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
static uint32 pg_atomic_fetch_or_u32(volatile pg_atomic_uint32 *ptr, uint32 or_)
Definition: atomics.h:372

◆ SendProcSignal()

int SendProcSignal ( pid_t  pid,
ProcSignalReason  reason,
BackendId  backendId 
)

Definition at line 261 of file procsignal.c.

References i, InvalidBackendId, kill, NumProcSignalSlots, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, and SIGUSR1.

Referenced by CancelDBBackends(), mq_putmessage(), ParallelWorkerShutdown(), pg_log_backend_memory_contexts(), SICleanupQueue(), SignalBackends(), SignalVirtualTransaction(), and WalSndInitStopping().

262 {
263  volatile ProcSignalSlot *slot;
264 
265  if (backendId != InvalidBackendId)
266  {
267  slot = &ProcSignal->psh_slot[backendId - 1];
268 
269  /*
270  * Note: Since there's no locking, it's possible that the target
271  * process detaches from shared memory and exits right after this
272  * test, before we set the flag and send signal. And the signal slot
273  * might even be recycled by a new process, so it's remotely possible
274  * that we set a flag for a wrong process. That's OK, all the signals
275  * are such that no harm is done if they're mistakenly fired.
276  */
277  if (slot->pss_pid == pid)
278  {
279  /* Atomically set the proper flag */
280  slot->pss_signalFlags[reason] = true;
281  /* Send signal */
282  return kill(pid, SIGUSR1);
283  }
284  }
285  else
286  {
287  /*
288  * BackendId not provided, so search the array using pid. We search
289  * the array back to front so as to reduce search overhead. Passing
290  * InvalidBackendId means that the target is most likely an auxiliary
291  * process, which will have a slot near the end of the array.
292  */
293  int i;
294 
295  for (i = NumProcSignalSlots - 1; i >= 0; i--)
296  {
297  slot = &ProcSignal->psh_slot[i];
298 
299  if (slot->pss_pid == pid)
300  {
301  /* the above note about race conditions applies here too */
302 
303  /* Atomically set the proper flag */
304  slot->pss_signalFlags[reason] = true;
305  /* Send signal */
306  return kill(pid, SIGUSR1);
307  }
308  }
309  }
310 
311  errno = ESRCH;
312  return -1;
313 }
volatile sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:65
#define SIGUSR1
Definition: win32_port.h:179
#define kill(pid, sig)
Definition: win32_port.h:464
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:80
volatile pid_t pss_pid
Definition: procsignal.c:64
#define InvalidBackendId
Definition: backendid.h:23
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
int i
#define NumProcSignalSlots
Definition: procsignal.c:88

◆ WaitForProcSignalBarrier()

void WaitForProcSignalBarrier ( uint64  generation)

Definition at line 392 of file procsignal.c.

References Assert, ConditionVariableCancelSleep(), ConditionVariableSleep(), i, NumProcSignalSlots, pg_atomic_read_u64(), pg_memory_barrier, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierCV, ProcSignalSlot::pss_barrierGeneration, and WAIT_EVENT_PROC_SIGNAL_BARRIER.

393 {
395 
396  for (int i = NumProcSignalSlots - 1; i >= 0; i--)
397  {
398  ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
399  uint64 oldval;
400 
401  /*
402  * It's important that we check only pss_barrierGeneration here and
403  * not pss_barrierCheckMask. Bits in pss_barrierCheckMask get cleared
404  * before the barrier is actually absorbed, but pss_barrierGeneration
405  * is updated only afterward.
406  */
407  oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
408  while (oldval < generation)
409  {
412  oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
413  }
415  }
416 
417  /*
418  * The caller is probably calling this function because it wants to read
419  * the shared state or perform further writes to shared state once all
420  * backends are known to have absorbed the barrier. However, the read of
421  * pss_barrierGeneration was performed unlocked; insert a memory barrier
422  * to separate it from whatever follows.
423  */
425 }
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:79
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:66
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:80
void ConditionVariableCancelSleep(void)
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:98
#define pg_memory_barrier()
Definition: atomics.h:145
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
#define Assert(condition)
Definition: c.h:804
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:429
int i
#define NumProcSignalSlots
Definition: procsignal.c:88
ConditionVariable pss_barrierCV
Definition: procsignal.c:68

Variable Documentation

◆ MyProcSignalSlot

ProcSignalSlot* MyProcSignalSlot = NULL
static

Definition at line 99 of file procsignal.c.

Referenced by CheckProcSignal().

◆ ProcSignal

ProcSignalHeader* ProcSignal = NULL
static

Definition at line 98 of file procsignal.c.