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/ipc.h"
#include "storage/latch.h"
#include "storage/proc.h"
#include "storage/shmem.h"
#include "storage/sinval.h"
#include "tcop/tcopprot.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 volatile ProcSignalSlotMyProcSignalSlot = NULL
 

Macro Definition Documentation

◆ BARRIER_CLEAR_BIT

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

Definition at line 92 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 88 of file procsignal.c.

◆ NumProcSignalSlots

Function Documentation

◆ CheckProcSignal()

static bool CheckProcSignal ( ProcSignalReason  reason)
static

Definition at line 631 of file procsignal.c.

References MyProcSignalSlot, and ProcSignalSlot::pss_signalFlags.

Referenced by procsignal_sigusr1_handler().

632 {
633  volatile ProcSignalSlot *slot = MyProcSignalSlot;
634 
635  if (slot != NULL)
636  {
637  /* Careful here --- don't clear flag if we haven't seen it set */
638  if (slot->pss_signalFlags[reason])
639  {
640  slot->pss_signalFlags[reason] = false;
641  return true;
642  }
643  }
644 
645  return false;
646 }
sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:63
static volatile ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:96

◆ CleanupProcSignalState()

static void CleanupProcSignalState ( int  status,
Datum  arg 
)
static

Definition at line 208 of file procsignal.c.

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

Referenced by ProcSignalInit().

209 {
210  int pss_idx = DatumGetInt32(arg);
211  volatile ProcSignalSlot *slot;
212 
213  slot = &ProcSignal->psh_slot[pss_idx - 1];
214  Assert(slot == MyProcSignalSlot);
215 
216  /*
217  * Clear MyProcSignalSlot, so that a SIGUSR1 received after this point
218  * won't try to access it after it's no longer ours (and perhaps even
219  * after we've unmapped the shared memory segment).
220  */
221  MyProcSignalSlot = NULL;
222 
223  /* sanity check */
224  if (slot->pss_pid != MyProcPid)
225  {
226  /*
227  * don't ERROR here. We're exiting anyway, and don't want to get into
228  * infinite loop trying to exit
229  */
230  elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d",
231  MyProcPid, pss_idx, (int) slot->pss_pid);
232  return; /* XXX better to zero the slot anyway? */
233  }
234 
235  /*
236  * Make this slot look like it's absorbed all possible barriers, so that
237  * no barrier waits block on it.
238  */
240 
241  slot->pss_pid = 0;
242 }
int MyProcPid
Definition: globals.c:41
#define PG_UINT64_MAX
Definition: c.h:516
#define DatumGetInt32(X)
Definition: postgres.h:472
#define LOG
Definition: elog.h:26
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:64
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:77
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:95
#define Assert(condition)
Definition: c.h:792
#define elog(elevel,...)
Definition: elog.h:228
void * arg
static volatile ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:96

◆ EmitProcSignalBarrier()

uint64 EmitProcSignalBarrier ( ProcSignalBarrierType  type)

Definition at line 327 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.

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

References InterruptPending, and ProcSignalBarrierPending.

Referenced by procsignal_sigusr1_handler().

449 {
450  InterruptPending = true;
452  /* latch will be set by procsignal_sigusr1_handler */
453 }
volatile sig_atomic_t ProcSignalBarrierPending
Definition: globals.c:36
volatile sig_atomic_t InterruptPending
Definition: globals.c:30

◆ ProcessBarrierPlaceholder()

static bool ProcessBarrierPlaceholder ( void  )
static

Definition at line 608 of file procsignal.c.

Referenced by ProcessProcSignalBarrier().

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

◆ ProcessProcSignalBarrier()

void ProcessProcSignalBarrier ( void  )

Definition at line 464 of file procsignal.c.

References Assert, BARRIER_CLEAR_BIT, 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_barrierGeneration, ResetProcSignalBarrierBits(), success, and generate_unaccent_rules::type.

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

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

References CheckProcSignal(), HandleCatchupInterrupt(), HandleNotifyInterrupt(), HandleParallelMessageInterrupt(), HandleProcSignalBarrierInterrupt(), HandleWalSndInitStopping(), latch_sigusr1_handler(), MyLatch, PROCSIG_BARRIER, PROCSIG_CATCHUP_INTERRUPT, 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(), PostgresMain(), StartBackgroundWorker(), StartupProcessMain(), WalReceiverMain(), WalSndSignals(), and WalWriterMain().

653 {
654  int save_errno = errno;
655 
658 
661 
664 
667 
670 
673 
676 
679 
682 
685 
688 
689  SetLatch(MyLatch);
690 
692 
693  errno = save_errno;
694 }
void RecoveryConflictInterrupt(ProcSignalReason reason)
Definition: postgres.c:2930
static void HandleProcSignalBarrierInterrupt(void)
Definition: procsignal.c:448
void SetLatch(Latch *latch)
Definition: latch.c:505
void HandleWalSndInitStopping(void)
Definition: walsender.c:3011
static bool CheckProcSignal(ProcSignalReason reason)
Definition: procsignal.c:631
void HandleNotifyInterrupt(void)
Definition: async.c:1889
struct Latch * MyLatch
Definition: globals.c:55
void HandleParallelMessageInterrupt(void)
Definition: parallel.c:992
void latch_sigusr1_handler(void)
Definition: latch.c:1944
void HandleCatchupInterrupt(void)
Definition: sinval.c:156

◆ ProcSignalInit()

void ProcSignalInit ( int  pss_idx)

Definition at line 157 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().

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

◆ ProcSignalShmemInit()

void ProcSignalShmemInit ( void  )

Definition at line 122 of file procsignal.c.

References 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_barrierGeneration, ProcSignalSlot::pss_pid, ProcSignalSlot::pss_signalFlags, and ShmemInitStruct().

Referenced by CreateSharedMemoryAndSemaphores().

123 {
124  Size size = ProcSignalShmemSize();
125  bool found;
126 
128  ShmemInitStruct("ProcSignal", size, &found);
129 
130  /* If we're first, initialize. */
131  if (!found)
132  {
133  int i;
134 
136 
137  for (i = 0; i < NumProcSignalSlots; ++i)
138  {
139  ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
140 
141  slot->pss_pid = 0;
142  MemSet(slot->pss_signalFlags, 0, sizeof(slot->pss_signalFlags));
145  }
146  }
147 }
#define PG_UINT64_MAX
Definition: c.h:516
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:76
#define MemSet(start, val, len)
Definition: c.h:996
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:64
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:77
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:65
Size ProcSignalShmemSize(void)
Definition: procsignal.c:108
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:95
size_t Size
Definition: c.h:528
int i
sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS]
Definition: procsignal.c:63
#define NumProcSignalSlots
Definition: procsignal.c:85
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:223

◆ ProcSignalShmemSize()

Size ProcSignalShmemSize ( void  )

Definition at line 108 of file procsignal.c.

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

Referenced by CreateSharedMemoryAndSemaphores(), and ProcSignalShmemInit().

109 {
110  Size size;
111 
112  size = mul_size(NumProcSignalSlots, sizeof(ProcSignalSlot));
113  size = add_size(size, offsetof(ProcSignalHeader, psh_slot));
114  return size;
115 }
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:528
#define NumProcSignalSlots
Definition: procsignal.c:85
#define offsetof(type, field)
Definition: c.h:715

◆ ResetProcSignalBarrierBits()

static void ResetProcSignalBarrierBits ( uint32  flags)
static

Definition at line 600 of file procsignal.c.

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

Referenced by ProcessProcSignalBarrier().

601 {
604  InterruptPending = true;
605 }
pg_atomic_uint32 pss_barrierCheckMask
Definition: procsignal.c:65
volatile sig_atomic_t ProcSignalBarrierPending
Definition: globals.c:36
volatile sig_atomic_t InterruptPending
Definition: globals.c:30
static volatile ProcSignalSlot * MyProcSignalSlot
Definition: procsignal.c:96
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 256 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(), SICleanupQueue(), SignalBackends(), SignalVirtualTransaction(), and WalSndInitStopping().

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

◆ WaitForProcSignalBarrier()

void WaitForProcSignalBarrier ( uint64  generation)

Definition at line 392 of file procsignal.c.

References Assert, CHECK_FOR_INTERRUPTS, i, Min, MyLatch, NumProcSignalSlots, pg_atomic_read_u64(), pg_memory_barrier, ProcSignalHeader::psh_barrierGeneration, ProcSignalHeader::psh_slot, ProcSignalSlot::pss_barrierGeneration, ResetLatch(), WAIT_EVENT_PROC_SIGNAL_BARRIER, WaitLatch(), WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, and WL_TIMEOUT.

393 {
394  long timeout = 125L;
395 
397 
398  for (int i = NumProcSignalSlots - 1; i >= 0; i--)
399  {
400  volatile ProcSignalSlot *slot = &ProcSignal->psh_slot[i];
401  uint64 oldval;
402 
403  /*
404  * It's important that we check only pss_barrierGeneration here and
405  * not pss_barrierCheckMask. Bits in pss_barrierCheckMask get cleared
406  * before the barrier is actually absorbed, but pss_barrierGeneration
407  * is updated only afterward.
408  */
409  oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
410  while (oldval < generation)
411  {
412  int events;
413 
415 
416  events =
421 
422  oldval = pg_atomic_read_u64(&slot->pss_barrierGeneration);
423  if (events & WL_TIMEOUT)
424  timeout = Min(timeout * 2, 1000L);
425  }
426  }
427 
428  /*
429  * The caller is probably calling this function because it wants to read
430  * the shared state or perform further writes to shared state once all
431  * backends are known to have absorbed the barrier. However, the read of
432  * pss_barrierGeneration was performed unlocked; insert a memory barrier
433  * to separate it from whatever follows.
434  */
436 }
#define WL_TIMEOUT
Definition: latch.h:127
pg_atomic_uint64 psh_barrierGeneration
Definition: procsignal.c:76
#define Min(x, y)
Definition: c.h:974
pg_atomic_uint64 pss_barrierGeneration
Definition: procsignal.c:64
void ResetLatch(Latch *latch)
Definition: latch.c:588
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:390
ProcSignalSlot psh_slot[FLEXIBLE_ARRAY_MEMBER]
Definition: procsignal.c:77
static ProcSignalHeader * ProcSignal
Definition: procsignal.c:95
#define pg_memory_barrier()
Definition: atomics.h:145
#define Assert(condition)
Definition: c.h:792
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:429
int i
#define NumProcSignalSlots
Definition: procsignal.c:85
struct Latch * MyLatch
Definition: globals.c:55
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:100
#define WL_LATCH_SET
Definition: latch.h:124
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:129

Variable Documentation

◆ MyProcSignalSlot

volatile ProcSignalSlot* MyProcSignalSlot = NULL
static

Definition at line 96 of file procsignal.c.

Referenced by CheckProcSignal().

◆ ProcSignal

ProcSignalHeader* ProcSignal = NULL
static

Definition at line 95 of file procsignal.c.