PostgreSQL Source Code  git master
proc.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
#include "replication/walsender.h"
#include "storage/condition_variable.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
#include "storage/spin.h"
#include "storage/standby.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
Include dependency graph for proc.c:

Go to the source code of this file.

Functions

static void RemoveProcFromArray (int code, Datum arg)
 
static void ProcKill (int code, Datum arg)
 
static void AuxiliaryProcKill (int code, Datum arg)
 
static void CheckDeadLock (void)
 
Size ProcGlobalShmemSize (void)
 
int ProcGlobalSemas (void)
 
void InitProcGlobal (void)
 
void InitProcess (void)
 
void InitProcessPhase2 (void)
 
void InitAuxiliaryProcess (void)
 
void SetStartupBufferPinWaitBufId (int bufid)
 
int GetStartupBufferPinWaitBufId (void)
 
bool HaveNFreeProcs (int n, int *nfree)
 
bool IsWaitingForLock (void)
 
void LockErrorCleanup (void)
 
void ProcReleaseLocks (bool isCommit)
 
PGPROCAuxiliaryPidGetProc (int pid)
 
ProcWaitStatus ProcSleep (LOCALLOCK *locallock, LockMethod lockMethodTable)
 
void ProcWakeup (PGPROC *proc, ProcWaitStatus waitStatus)
 
void ProcLockWakeup (LockMethod lockMethodTable, LOCK *lock)
 
void CheckDeadLockAlert (void)
 
void ProcWaitForSignal (uint32 wait_event_info)
 
void ProcSendSignal (int pgprocno)
 
void BecomeLockGroupLeader (void)
 
bool BecomeLockGroupMember (PGPROC *leader, int pid)
 

Variables

int DeadlockTimeout = 1000
 
int StatementTimeout = 0
 
int LockTimeout = 0
 
int IdleInTransactionSessionTimeout = 0
 
int IdleSessionTimeout = 0
 
bool log_lock_waits = false
 
PGPROCMyProc = NULL
 
NON_EXEC_STATIC slock_tProcStructLock = NULL
 
PROC_HDRProcGlobal = NULL
 
NON_EXEC_STATIC PGPROCAuxiliaryProcs = NULL
 
PGPROCPreparedXactProcs = NULL
 
static LOCALLOCKlockAwaited = NULL
 
static DeadLockState deadlock_state = DS_NOT_YET_CHECKED
 
static volatile sig_atomic_t got_deadlock_timeout
 

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC* AuxiliaryPidGetProc ( int  pid)

Definition at line 965 of file proc.c.

966 {
967  PGPROC *result = NULL;
968  int index;
969 
970  if (pid == 0) /* never match dummy PGPROCs */
971  return NULL;
972 
973  for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
974  {
975  PGPROC *proc = &AuxiliaryProcs[index];
976 
977  if (proc->pid == pid)
978  {
979  result = proc;
980  break;
981  }
982  }
983  return result;
984 }
#define NUM_AUXILIARY_PROCS
Definition: proc.h:418
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:79
Definition: proc.h:162
int pid
Definition: proc.h:186
Definition: type.h:95

References AuxiliaryProcs, NUM_AUXILIARY_PROCS, and PGPROC::pid.

Referenced by pg_log_backend_memory_contexts(), and pg_stat_get_activity().

◆ AuxiliaryProcKill()

static void AuxiliaryProcKill ( int  code,
Datum  arg 
)
static

Definition at line 921 of file proc.c.

922 {
923  int proctype = DatumGetInt32(arg);
925  PGPROC *proc;
926 
927  Assert(proctype >= 0 && proctype < NUM_AUXILIARY_PROCS);
928 
929  auxproc = &AuxiliaryProcs[proctype];
930 
931  Assert(MyProc == auxproc);
932 
933  /* Release any LW locks I am holding (see notes above) */
935 
936  /* Cancel any pending condition variable sleep, too */
938 
939  /* look at the equivalent ProcKill() code for comments */
942 
943  proc = MyProc;
944  MyProc = NULL;
945  DisownLatch(&proc->procLatch);
946 
948 
949  /* Mark auxiliary proc no longer in use */
950  proc->pid = 0;
951 
952  /* Update shared estimate of spins_per_delay */
954 
956 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:171
bool ConditionVariableCancelSleep(void)
void DisownLatch(Latch *latch)
Definition: latch.c:462
Assert(fmt[strlen(fmt) - 1] !='\n')
void LWLockReleaseAll(void)
Definition: lwlock.c:1903
void SwitchBackToLocalLatch(void)
Definition: miscinit.c:249
void * arg
static int32 DatumGetInt32(Datum X)
Definition: postgres.h:202
int update_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:218
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
PGPROC * MyProc
Definition: proc.c:66
PROC_HDR * ProcGlobal
Definition: proc.c:78
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:75
Latch procLatch
Definition: proc.h:170
int spins_per_delay
Definition: proc.h:398
void pgstat_reset_wait_event_storage(void)
Definition: wait_event.c:328

References arg, Assert(), AuxiliaryProcs, ConditionVariableCancelSleep(), DatumGetInt32(), DisownLatch(), LWLockReleaseAll(), MyProc, NUM_AUXILIARY_PROCS, PG_USED_FOR_ASSERTS_ONLY, pgstat_reset_wait_event_storage(), PGPROC::pid, ProcGlobal, PGPROC::procLatch, ProcStructLock, SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, SwitchBackToLocalLatch(), and update_spins_per_delay().

Referenced by InitAuxiliaryProcess().

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 1824 of file proc.c.

1825 {
1826  LWLock *leader_lwlock;
1827 
1828  /* If we already did it, we don't need to do it again. */
1829  if (MyProc->lockGroupLeader == MyProc)
1830  return;
1831 
1832  /* We had better not be a follower. */
1833  Assert(MyProc->lockGroupLeader == NULL);
1834 
1835  /* Create single-member group, containing only ourselves. */
1836  leader_lwlock = LockHashPartitionLockByProc(MyProc);
1837  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1840  LWLockRelease(leader_lwlock);
1841 }
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:542
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_EXCLUSIVE
Definition: lwlock.h:116
Definition: lwlock.h:41
dlist_head lockGroupMembers
Definition: proc.h:296
dlist_node lockGroupLink
Definition: proc.h:297
PGPROC * lockGroupLeader
Definition: proc.h:295

References Assert(), dlist_push_head(), PGPROC::lockGroupLeader, PGPROC::lockGroupLink, PGPROC::lockGroupMembers, LockHashPartitionLockByProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and MyProc.

Referenced by LaunchParallelWorkers().

◆ BecomeLockGroupMember()

bool BecomeLockGroupMember ( PGPROC leader,
int  pid 
)

Definition at line 1854 of file proc.c.

1855 {
1856  LWLock *leader_lwlock;
1857  bool ok = false;
1858 
1859  /* Group leader can't become member of group */
1860  Assert(MyProc != leader);
1861 
1862  /* Can't already be a member of a group */
1863  Assert(MyProc->lockGroupLeader == NULL);
1864 
1865  /* PID must be valid. */
1866  Assert(pid != 0);
1867 
1868  /*
1869  * Get lock protecting the group fields. Note LockHashPartitionLockByProc
1870  * accesses leader->pgprocno in a PGPROC that might be free. This is safe
1871  * because all PGPROCs' pgprocno fields are set during shared memory
1872  * initialization and never change thereafter; so we will acquire the
1873  * correct lock even if the leader PGPROC is in process of being recycled.
1874  */
1875  leader_lwlock = LockHashPartitionLockByProc(leader);
1876  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1877 
1878  /* Is this the leader we're looking for? */
1879  if (leader->pid == pid && leader->lockGroupLeader == leader)
1880  {
1881  /* OK, join the group */
1882  ok = true;
1883  MyProc->lockGroupLeader = leader;
1885  }
1886  LWLockRelease(leader_lwlock);
1887 
1888  return ok;
1889 }
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364

References Assert(), dlist_push_tail(), PGPROC::lockGroupLeader, PGPROC::lockGroupLink, PGPROC::lockGroupMembers, LockHashPartitionLockByProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, and PGPROC::pid.

Referenced by ParallelWorkerMain().

◆ CheckDeadLock()

static void CheckDeadLock ( void  )
static

Definition at line 1685 of file proc.c.

1686 {
1687  int i;
1688 
1689  /*
1690  * Acquire exclusive lock on the entire shared lock data structures. Must
1691  * grab LWLocks in partition-number order to avoid LWLock deadlock.
1692  *
1693  * Note that the deadlock check interrupt had better not be enabled
1694  * anywhere that this process itself holds lock partition locks, else this
1695  * will wait forever. Also note that LWLockAcquire creates a critical
1696  * section, so that this routine cannot be interrupted by cancel/die
1697  * interrupts.
1698  */
1699  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
1701 
1702  /*
1703  * Check to see if we've been awoken by anyone in the interim.
1704  *
1705  * If we have, we can return and resume our transaction -- happy day.
1706  * Before we are awoken the process releasing the lock grants it to us so
1707  * we know that we don't have to wait anymore.
1708  *
1709  * We check by looking to see if we've been unlinked from the wait queue.
1710  * This is safe because we hold the lock partition lock.
1711  */
1712  if (MyProc->links.prev == NULL ||
1713  MyProc->links.next == NULL)
1714  goto check_done;
1715 
1716 #ifdef LOCK_DEBUG
1717  if (Debug_deadlocks)
1718  DumpAllLocks();
1719 #endif
1720 
1721  /* Run the deadlock check, and set deadlock_state for use by ProcSleep */
1723 
1725  {
1726  /*
1727  * Oops. We have a deadlock.
1728  *
1729  * Get this process out of wait state. (Note: we could do this more
1730  * efficiently by relying on lockAwaited, but use this coding to
1731  * preserve the flexibility to kill some other transaction than the
1732  * one detecting the deadlock.)
1733  *
1734  * RemoveFromWaitQueue sets MyProc->waitStatus to
1735  * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
1736  * return from the signal handler.
1737  */
1738  Assert(MyProc->waitLock != NULL);
1740 
1741  /*
1742  * We're done here. Transaction abort caused by the error that
1743  * ProcSleep will raise will cause any other locks we hold to be
1744  * released, thus allowing other processes to wake up; we don't need
1745  * to do that here. NOTE: an exception is that releasing locks we
1746  * hold doesn't consider the possibility of waiters that were blocked
1747  * behind us on the lock we just failed to get, and might now be
1748  * wakable because we're not in front of them anymore. However,
1749  * RemoveFromWaitQueue took care of waking up any such processes.
1750  */
1751  }
1752 
1753  /*
1754  * And release locks. We do this in reverse order for two reasons: (1)
1755  * Anyone else who needs more than one of the locks will be trying to lock
1756  * them in increasing order; we don't want to release the other process
1757  * until it can get all the locks it needs. (2) This avoids O(N^2)
1758  * behavior inside LWLockRelease.
1759  */
1760 check_done:
1761  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
1763 }
DeadLockState DeadLockCheck(PGPROC *proc)
Definition: deadlock.c:217
int i
Definition: isn.c:73
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1869
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:505
@ DS_HARD_DEADLOCK
Definition: lock.h:514
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:530
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:99
static DeadLockState deadlock_state
Definition: proc.c:85
LOCKTAG tag
Definition: lock.h:311
LOCK * waitLock
Definition: proc.h:223
dlist_node links
Definition: proc.h:164
dlist_node * next
Definition: ilist.h:140
dlist_node * prev
Definition: ilist.h:139

References Assert(), deadlock_state, DeadLockCheck(), DS_HARD_DEADLOCK, i, PGPROC::links, LockHashPartitionLockByIndex, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, dlist_node::next, NUM_LOCK_PARTITIONS, dlist_node::prev, RemoveFromWaitQueue(), LOCK::tag, and PGPROC::waitLock.

Referenced by ProcSleep().

◆ CheckDeadLockAlert()

void CheckDeadLockAlert ( void  )

Definition at line 1771 of file proc.c.

1772 {
1773  int save_errno = errno;
1774 
1775  got_deadlock_timeout = true;
1776 
1777  /*
1778  * Have to set the latch again, even if handle_sig_alarm already did. Back
1779  * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1780  * ever would be a problem, but setting a set latch again is cheap.
1781  *
1782  * Note that, when this function runs inside procsignal_sigusr1_handler(),
1783  * the handler function sets the latch again after the latch is set here.
1784  */
1785  SetLatch(MyLatch);
1786  errno = save_errno;
1787 }
struct Latch * MyLatch
Definition: globals.c:58
void SetLatch(Latch *latch)
Definition: latch.c:605
static volatile sig_atomic_t got_deadlock_timeout
Definition: proc.c:88

References got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres(), and ProcessRecoveryConflictInterrupt().

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 639 of file proc.c.

640 {
641  /* use volatile pointer to prevent code rearrangement */
642  volatile PROC_HDR *procglobal = ProcGlobal;
643 
644  return procglobal->startupBufferPinWaitBufId;
645 }
Definition: proc.h:360
int startupBufferPinWaitBufId
Definition: proc.h:400

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and ProcessRecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int *  nfree 
)

Definition at line 655 of file proc.c.

656 {
657  dlist_iter iter;
658 
659  Assert(n > 0);
660  Assert(nfree);
661 
663 
664  *nfree = 0;
666  {
667  (*nfree)++;
668  if (*nfree == n)
669  break;
670  }
671 
673 
674  return (*nfree == n);
675 }
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
dlist_head freeProcs
Definition: proc.h:382

References Assert(), dlist_foreach, PROC_HDR::freeProcs, ProcGlobal, ProcStructLock, SpinLockAcquire, and SpinLockRelease.

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 509 of file proc.c.

510 {
511  PGPROC *auxproc;
512  int proctype;
513 
514  /*
515  * ProcGlobal should be set up already (if we are a backend, we inherit
516  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
517  */
518  if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
519  elog(PANIC, "proc header uninitialized");
520 
521  if (MyProc != NULL)
522  elog(ERROR, "you already exist");
523 
524  /*
525  * We use the ProcStructLock to protect assignment and releasing of
526  * AuxiliaryProcs entries.
527  *
528  * While we are holding the ProcStructLock, also copy the current shared
529  * estimate of spins_per_delay to local storage.
530  */
532 
534 
535  /*
536  * Find a free auxproc ... *big* trouble if there isn't one ...
537  */
538  for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
539  {
540  auxproc = &AuxiliaryProcs[proctype];
541  if (auxproc->pid == 0)
542  break;
543  }
544  if (proctype >= NUM_AUXILIARY_PROCS)
545  {
547  elog(FATAL, "all AuxiliaryProcs are in use");
548  }
549 
550  /* Mark auxiliary proc as in use by me */
551  /* use volatile pointer to prevent code rearrangement */
552  ((volatile PGPROC *) auxproc)->pid = MyProcPid;
553 
554  MyProc = auxproc;
555 
557 
558  /*
559  * Initialize all fields of MyProc, except for those previously
560  * initialized by InitProcGlobal.
561  */
565  MyProc->fpVXIDLock = false;
574  MyProc->delayChkptFlags = 0;
575  MyProc->statusFlags = 0;
577  MyProc->lwWaitMode = 0;
578  MyProc->waitLock = NULL;
579  MyProc->waitProcLock = NULL;
581 #ifdef USE_ASSERT_CHECKING
582  {
583  int i;
584 
585  /* Last process should have released all locks. */
586  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
588  }
589 #endif
590 
591  /*
592  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
593  * on it. That allows us to repoint the process latch, which so far
594  * points to process local one, to the shared one.
595  */
598 
599  /* now that we have a proc, report wait events to shared memory */
601 
602  /* Check that group locking fields are in a proper initial state. */
603  Assert(MyProc->lockGroupLeader == NULL);
605 
606  /*
607  * We might be reusing a semaphore that belonged to a failed process. So
608  * be careful and reinitialize its value here. (This is not strictly
609  * necessary anymore, but seems like a good idea for cleanliness.)
610  */
612 
613  /*
614  * Arrange to clean up at process exit.
615  */
617 }
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:433
#define InvalidBackendId
Definition: backendid.h:23
#define FATAL
Definition: elog.h:41
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
int MyProcPid
Definition: globals.c:44
bool IsBackgroundWorker
Definition: globals.c:115
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
static void dlist_node_init(dlist_node *node)
Definition: ilist.h:325
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
void OwnLatch(Latch *latch)
Definition: latch.c:436
#define InvalidLocalTransactionId
Definition: lock.h:65
@ LW_WS_NOT_WAITING
Definition: lwlock.h:29
void SwitchToSharedLatch(void)
Definition: miscinit.c:222
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:295
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
@ PROC_WAIT_STATUS_OK
Definition: proc.h:124
void set_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:207
static void AuxiliaryProcKill(int code, Datum arg)
Definition: proc.c:921
TransactionId xmin
Definition: proc.h:178
LocalTransactionId lxid
Definition: proc.h:183
PROCLOCK * waitProcLock
Definition: proc.h:224
uint8 lwWaitMode
Definition: proc.h:215
uint32 wait_event_info
Definition: proc.h:270
uint8 statusFlags
Definition: proc.h:233
Oid databaseId
Definition: proc.h:198
pg_atomic_uint64 waitStart
Definition: proc.h:228
bool fpVXIDLock
Definition: proc.h:287
BackendId backendId
Definition: proc.h:197
bool isBackgroundWorker
Definition: proc.h:204
TransactionId xid
Definition: proc.h:173
int delayChkptFlags
Definition: proc.h:231
LocalTransactionId fpLocalTransactionId
Definition: proc.h:288
PGSemaphore sem
Definition: proc.h:167
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:252
Oid roleId
Definition: proc.h:199
ProcWaitStatus waitStatus
Definition: proc.h:168
Oid tempNamespaceId
Definition: proc.h:201
uint8 lwWaiting
Definition: proc.h:214
#define InvalidTransactionId
Definition: transam.h:31
void pgstat_set_wait_event_storage(uint32 *wait_event_info)
Definition: wait_event.c:316

References Assert(), AuxiliaryProcKill(), AuxiliaryProcs, PGPROC::backendId, PGPROC::databaseId, PGPROC::delayChkptFlags, dlist_is_empty(), dlist_node_init(), elog(), ERROR, FATAL, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, i, Int32GetDatum(), InvalidBackendId, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, IsBackgroundWorker, PGPROC::isBackgroundWorker, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LW_WS_NOT_WAITING, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, MyProc, PGPROC::myProcLocks, MyProcPid, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, on_shmem_exit(), OwnLatch(), PANIC, pg_atomic_write_u64(), PGSemaphoreReset(), pgstat_set_wait_event_storage(), PGPROC::pid, PROC_WAIT_STATUS_OK, ProcGlobal, PGPROC::procLatch, ProcStructLock, PGPROC::roleId, PGPROC::sem, set_spins_per_delay(), SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, PGPROC::statusFlags, SwitchToSharedLatch(), PGPROC::tempNamespaceId, PGPROC::wait_event_info, PGPROC::waitLock, PGPROC::waitProcLock, PGPROC::waitStart, PGPROC::waitStatus, PGPROC::xid, and PGPROC::xmin.

Referenced by AuxiliaryProcessMain().

◆ InitProcess()

void InitProcess ( void  )

Definition at line 297 of file proc.c.

298 {
299  dlist_head *procgloballist;
300 
301  /*
302  * ProcGlobal should be set up already (if we are a backend, we inherit
303  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
304  */
305  if (ProcGlobal == NULL)
306  elog(PANIC, "proc header uninitialized");
307 
308  if (MyProc != NULL)
309  elog(ERROR, "you already exist");
310 
311  /* Decide which list should supply our PGPROC. */
313  procgloballist = &ProcGlobal->autovacFreeProcs;
314  else if (IsBackgroundWorker)
315  procgloballist = &ProcGlobal->bgworkerFreeProcs;
316  else if (am_walsender)
317  procgloballist = &ProcGlobal->walsenderFreeProcs;
318  else
319  procgloballist = &ProcGlobal->freeProcs;
320 
321  /*
322  * Try to get a proc struct from the appropriate free list. If this
323  * fails, we must be out of PGPROC structures (not to mention semaphores).
324  *
325  * While we are holding the ProcStructLock, also copy the current shared
326  * estimate of spins_per_delay to local storage.
327  */
329 
331 
332  if (!dlist_is_empty(procgloballist))
333  {
334  MyProc = (PGPROC *) dlist_pop_head_node(procgloballist);
336  }
337  else
338  {
339  /*
340  * If we reach here, all the PGPROCs are in use. This is one of the
341  * possible places to detect "too many backends", so give the standard
342  * error message. XXX do we need to give a different failure message
343  * in the autovacuum case?
344  */
346  if (am_walsender)
347  ereport(FATAL,
348  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
349  errmsg("number of requested standby connections exceeds max_wal_senders (currently %d)",
350  max_wal_senders)));
351  ereport(FATAL,
352  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
353  errmsg("sorry, too many clients already")));
354  }
355 
356  /*
357  * Cross-check that the PGPROC is of the type we expect; if this were not
358  * the case, it would get returned to the wrong list.
359  */
360  Assert(MyProc->procgloballist == procgloballist);
361 
362  /*
363  * Now that we have a PGPROC, mark ourselves as an active postmaster
364  * child; this is so that the postmaster can detect it if we exit without
365  * cleaning up. (XXX autovac launcher currently doesn't participate in
366  * this; it probably should.)
367  */
370 
371  /*
372  * Initialize all fields of MyProc, except for those previously
373  * initialized by InitProcGlobal.
374  */
378  MyProc->fpVXIDLock = false;
382  MyProc->pid = MyProcPid;
383  /* backendId, databaseId and roleId will be filled in later */
389  MyProc->delayChkptFlags = 0;
390  MyProc->statusFlags = 0;
391  /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
395  MyProc->lwWaitMode = 0;
396  MyProc->waitLock = NULL;
397  MyProc->waitProcLock = NULL;
399 #ifdef USE_ASSERT_CHECKING
400  {
401  int i;
402 
403  /* Last process should have released all locks. */
404  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
406  }
407 #endif
409 
410  /* Initialize fields for sync rep */
411  MyProc->waitLSN = 0;
414 
415  /* Initialize fields for group XID clearing. */
416  MyProc->procArrayGroupMember = false;
419 
420  /* Check that group locking fields are in a proper initial state. */
421  Assert(MyProc->lockGroupLeader == NULL);
423 
424  /* Initialize wait event information. */
425  MyProc->wait_event_info = 0;
426 
427  /* Initialize fields for group transaction status update. */
428  MyProc->clogGroupMember = false;
434 
435  /*
436  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
437  * on it. That allows us to repoint the process latch, which so far
438  * points to process local one, to the shared one.
439  */
442 
443  /* now that we have a proc, report wait events to shared memory */
445 
446  /*
447  * We might be reusing a semaphore that belonged to a failed process. So
448  * be careful and reinitialize its value here. (This is not strictly
449  * necessary anymore, but seems like a good idea for cleanliness.)
450  */
452 
453  /*
454  * Arrange to clean up at backend exit.
455  */
457 
458  /*
459  * Now that we have a PGPROC, we could try to acquire locks, so initialize
460  * local state needed for LWLocks, and the deadlock checker.
461  */
464 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3391
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3397
#define IsAnyAutoVacuumProcess()
Definition: autovacuum.h:55
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:27
void InitDeadLockChecking(void)
Definition: deadlock.c:143
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
bool IsUnderPostmaster
Definition: globals.c:113
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition: ilist.h:450
void InitLWLockAccess(void)
Definition: lwlock.c:581
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:323
#define INVALID_PGPROCNO
Definition: proc.h:85
#define PROC_IS_AUTOVACUUM
Definition: proc.h:56
static void ProcKill(int code, Datum arg)
Definition: proc.c:802
bool procArrayGroupMember
Definition: proc.h:260
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:280
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:262
int clogGroupMemberPage
Definition: proc.h:278
dlist_head * procgloballist
Definition: proc.h:165
bool recoveryConflictPending
Definition: proc.h:211
TransactionId clogGroupMemberXid
Definition: proc.h:275
bool clogGroupMember
Definition: proc.h:273
XLogRecPtr waitLSN
Definition: proc.h:243
dlist_node syncRepLinks
Definition: proc.h:245
int syncRepState
Definition: proc.h:244
pg_atomic_uint32 clogGroupNext
Definition: proc.h:274
XidStatus clogGroupMemberXidStatus
Definition: proc.h:276
TransactionId procArrayGroupMemberXid
Definition: proc.h:268
dlist_head autovacFreeProcs
Definition: proc.h:384
dlist_head walsenderFreeProcs
Definition: proc.h:388
dlist_head bgworkerFreeProcs
Definition: proc.h:386
#define SYNC_REP_NOT_WAITING
Definition: syncrep.h:30
bool am_walsender
Definition: walsender.c:116
int max_wal_senders
Definition: walsender.c:122
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

References am_walsender, Assert(), PROC_HDR::autovacFreeProcs, PGPROC::backendId, PROC_HDR::bgworkerFreeProcs, PGPROC::clogGroupMember, PGPROC::clogGroupMemberLsn, PGPROC::clogGroupMemberPage, PGPROC::clogGroupMemberXid, PGPROC::clogGroupMemberXidStatus, PGPROC::clogGroupNext, PGPROC::databaseId, PGPROC::delayChkptFlags, dlist_is_empty(), dlist_node_init(), dlist_pop_head_node(), elog(), ereport, errcode(), errmsg(), ERROR, FATAL, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, PROC_HDR::freeProcs, i, InitDeadLockChecking(), InitLWLockAccess(), INVALID_PGPROCNO, InvalidBackendId, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsAnyAutoVacuumProcess, IsAutoVacuumLauncherProcess(), IsAutoVacuumWorkerProcess(), IsBackgroundWorker, PGPROC::isBackgroundWorker, IsUnderPostmaster, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LW_WS_NOT_WAITING, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, MarkPostmasterChildActive(), max_wal_senders, MyProc, PGPROC::myProcLocks, MyProcPid, NUM_LOCK_PARTITIONS, on_shmem_exit(), OwnLatch(), PANIC, pg_atomic_read_u32(), pg_atomic_write_u64(), PGSemaphoreReset(), pgstat_set_wait_event_storage(), PGPROC::pid, PROC_IS_AUTOVACUUM, PROC_WAIT_STATUS_OK, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::procgloballist, ProcKill(), PGPROC::procLatch, ProcStructLock, PGPROC::recoveryConflictPending, PGPROC::roleId, PGPROC::sem, set_spins_per_delay(), SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, PGPROC::statusFlags, SwitchToSharedLatch(), SYNC_REP_NOT_WAITING, PGPROC::syncRepLinks, PGPROC::syncRepState, PGPROC::tempNamespaceId, TRANSACTION_STATUS_IN_PROGRESS, PGPROC::wait_event_info, PGPROC::waitLock, PGPROC::waitLSN, PGPROC::waitProcLock, PGPROC::waitStart, PGPROC::waitStatus, PROC_HDR::walsenderFreeProcs, PGPROC::xid, and PGPROC::xmin.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackendStartup(), BootstrapModeMain(), PostgresSingleUserMain(), and StartBackgroundWorker().

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 474 of file proc.c.

475 {
476  Assert(MyProc != NULL);
477 
478  /*
479  * Add our PGPROC to the PGPROC array in shared memory.
480  */
482 
483  /*
484  * Arrange to clean that up at backend exit.
485  */
487 }
void ProcArrayAdd(PGPROC *proc)
Definition: procarray.c:469
static void RemoveProcFromArray(int code, Datum arg)
Definition: proc.c:791

References Assert(), MyProc, on_shmem_exit(), ProcArrayAdd(), and RemoveProcFromArray().

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 157 of file proc.c.

158 {
159  PGPROC *procs;
160  int i,
161  j;
162  bool found;
164 
165  /* Create the ProcGlobal shared structure */
166  ProcGlobal = (PROC_HDR *)
167  ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
168  Assert(!found);
169 
170  /*
171  * Initialize the data structures.
172  */
179  ProcGlobal->walwriterLatch = NULL;
183 
184  /*
185  * Create and initialize all the PGPROC structures we'll need. There are
186  * five separate consumers: (1) normal backends, (2) autovacuum workers
187  * and the autovacuum launcher, (3) background workers, (4) auxiliary
188  * processes, and (5) prepared transactions. Each PGPROC structure is
189  * dedicated to exactly one of these purposes, and they do not move
190  * between groups.
191  */
192  procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
193  MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
194  ProcGlobal->allProcs = procs;
195  /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
197 
198  /*
199  * Allocate arrays mirroring PGPROC fields in a dense manner. See
200  * PROC_HDR.
201  *
202  * XXX: It might make sense to increase padding for these arrays, given
203  * how hotly they are accessed.
204  */
205  ProcGlobal->xids =
206  (TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids));
207  MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids));
209  MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates));
210  ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags));
211  MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags));
212 
213  for (i = 0; i < TotalProcs; i++)
214  {
215  PGPROC *proc = &procs[i];
216 
217  /* Common initialization for all PGPROCs, regardless of type. */
218 
219  /*
220  * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
221  * dummy PGPROCs don't need these though - they're never associated
222  * with a real process
223  */
225  {
226  proc->sem = PGSemaphoreCreate();
227  InitSharedLatch(&(proc->procLatch));
229  }
230  proc->pgprocno = i;
231 
232  /*
233  * Newly created PGPROCs for normal backends, autovacuum and bgworkers
234  * must be queued up on the appropriate free list. Because there can
235  * only ever be a small, fixed number of auxiliary processes, no free
236  * list is used in that case; InitAuxiliaryProcess() instead uses a
237  * linear search. PGPROCs for prepared transactions are added to a
238  * free list by TwoPhaseShmemInit().
239  */
240  if (i < MaxConnections)
241  {
242  /* PGPROC for normal backend, add to freeProcs list */
245  }
246  else if (i < MaxConnections + autovacuum_max_workers + 1)
247  {
248  /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */
251  }
253  {
254  /* PGPROC for bgworker, add to bgworkerFreeProcs list */
257  }
258  else if (i < MaxBackends)
259  {
260  /* PGPROC for walsender, add to walsenderFreeProcs list */
263  }
264 
265  /* Initialize myProcLocks[] shared memory queues. */
266  for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
267  dlist_init(&(proc->myProcLocks[j]));
268 
269  /* Initialize lockGroupMembers list. */
271 
272  /*
273  * Initialize the atomic variables, otherwise, it won't be safe to
274  * access them for backends that aren't currently in use.
275  */
278  pg_atomic_init_u64(&(proc->waitStart), 0);
279  }
280 
281  /*
282  * Save pointers to the blocks of PGPROC structures reserved for auxiliary
283  * processes and prepared transactions.
284  */
285  AuxiliaryProcs = &procs[MaxBackends];
287 
288  /* Create ProcStructLock spinlock, too */
289  ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
291 }
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:218
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:410
int autovacuum_max_workers
Definition: autovacuum.c:117
unsigned int uint32
Definition: c.h:495
unsigned char uint8
Definition: c.h:493
#define MemSet(start, val, len)
Definition: c.h:1009
uint32 TransactionId
Definition: c.h:641
int MaxConnections
Definition: globals.c:137
int MaxBackends
Definition: globals.c:140
int max_worker_processes
Definition: globals.c:138
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
int j
Definition: isn.c:74
void InitSharedLatch(Latch *latch)
Definition: latch.c:403
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:730
@ LWTRANCHE_LOCK_FASTPATH
Definition: lwlock.h:192
PGSemaphore PGSemaphoreCreate(void)
Definition: posix_sema.c:262
#define DEFAULT_SPINS_PER_DELAY
Definition: s_lock.h:832
int slock_t
Definition: s_lock.h:754
void * ShmemAlloc(Size size)
Definition: shmem.c:161
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
#define SpinLockInit(lock)
Definition: spin.h:60
PGPROC * PreparedXactProcs
Definition: proc.c:80
LWLock fpInfoLock
Definition: proc.h:284
int pgprocno
Definition: proc.h:191
uint8 * statusFlags
Definition: proc.h:377
XidCacheStatus * subxidStates
Definition: proc.h:371
Latch * walwriterLatch
Definition: proc.h:394
PGPROC * allProcs
Definition: proc.h:362
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:392
TransactionId * xids
Definition: proc.h:365
Latch * checkpointerLatch
Definition: proc.h:396
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:390
uint32 allProcCount
Definition: proc.h:380
int max_prepared_xacts
Definition: twophase.c:118

References PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert(), PROC_HDR::autovacFreeProcs, autovacuum_max_workers, AuxiliaryProcs, PROC_HDR::bgworkerFreeProcs, PROC_HDR::checkpointerLatch, PROC_HDR::clogGroupFirst, PGPROC::clogGroupNext, DEFAULT_SPINS_PER_DELAY, dlist_init(), dlist_push_head(), PGPROC::fpInfoLock, PROC_HDR::freeProcs, i, InitSharedLatch(), INVALID_PGPROCNO, j, PGPROC::links, PGPROC::lockGroupMembers, LWLockInitialize(), LWTRANCHE_LOCK_FASTPATH, max_prepared_xacts, max_worker_processes, MaxBackends, MaxConnections, MemSet, PGPROC::myProcLocks, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, pg_atomic_init_u32(), pg_atomic_init_u64(), PGPROC::pgprocno, PGSemaphoreCreate(), PreparedXactProcs, PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::procgloballist, PGPROC::procLatch, ProcStructLock, PGPROC::sem, ShmemAlloc(), ShmemInitStruct(), SpinLockInit, PROC_HDR::spins_per_delay, PROC_HDR::startupBufferPinWaitBufId, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PGPROC::waitStart, PROC_HDR::walsenderFreeProcs, PROC_HDR::walwriterLatch, and PROC_HDR::xids.

Referenced by CreateSharedMemoryAndSemaphores().

◆ IsWaitingForLock()

bool IsWaitingForLock ( void  )

Definition at line 681 of file proc.c.

682 {
683  if (lockAwaited == NULL)
684  return false;
685 
686  return true;
687 }
static LOCALLOCK * lockAwaited
Definition: proc.c:83

References lockAwaited.

Referenced by ProcessRecoveryConflictInterrupt().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 698 of file proc.c.

699 {
700  LWLock *partitionLock;
701  DisableTimeoutParams timeouts[2];
702 
703  HOLD_INTERRUPTS();
704 
706 
707  /* Nothing to do if we weren't waiting for a lock */
708  if (lockAwaited == NULL)
709  {
711  return;
712  }
713 
714  /*
715  * Turn off the deadlock and lock timeout timers, if they are still
716  * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
717  * indicator flag, since this function is executed before
718  * ProcessInterrupts when responding to SIGINT; else we'd lose the
719  * knowledge that the SIGINT came from a lock timeout and not an external
720  * source.
721  */
722  timeouts[0].id = DEADLOCK_TIMEOUT;
723  timeouts[0].keep_indicator = false;
724  timeouts[1].id = LOCK_TIMEOUT;
725  timeouts[1].keep_indicator = true;
726  disable_timeouts(timeouts, 2);
727 
728  /* Unlink myself from the wait queue, if on it (might not be anymore!) */
729  partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
730  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
731 
733  {
734  /* We could not have been granted the lock yet */
736  }
737  else
738  {
739  /*
740  * Somebody kicked us off the lock queue already. Perhaps they
741  * granted us the lock, or perhaps they detected a deadlock. If they
742  * did grant us the lock, we'd better remember it in our local lock
743  * table.
744  */
747  }
748 
749  lockAwaited = NULL;
750 
751  LWLockRelease(partitionLock);
752 
754 }
static bool dlist_node_is_detached(const dlist_node *node)
Definition: ilist.h:525
void GrantAwaitedLock(void)
Definition: lock.c:1757
void AbortStrongLockAcquire(void)
Definition: lock.c:1728
#define LockHashPartitionLock(hashcode)
Definition: lock.h:527
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:134
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:132
TimeoutId id
Definition: timeout.h:70
uint32 hashcode
Definition: lock.h:432
void disable_timeouts(const DisableTimeoutParams *timeouts, int count)
Definition: timeout.c:722
@ LOCK_TIMEOUT
Definition: timeout.h:28
@ DEADLOCK_TIMEOUT
Definition: timeout.h:27

References AbortStrongLockAcquire(), DEADLOCK_TIMEOUT, disable_timeouts(), dlist_node_is_detached(), GrantAwaitedLock(), LOCALLOCK::hashcode, HOLD_INTERRUPTS, DisableTimeoutParams::id, DisableTimeoutParams::keep_indicator, PGPROC::links, LOCK_TIMEOUT, lockAwaited, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), RESUME_INTERRUPTS, and PGPROC::waitStatus.

Referenced by AbortSubTransaction(), AbortTransaction(), ProcessInterrupts(), ProcessRecoveryConflictInterrupt(), and ProcReleaseLocks().

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 122 of file proc.c.

123 {
124  /*
125  * We need a sema per backend (including autovacuum), plus one for each
126  * auxiliary process.
127  */
129 }

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 100 of file proc.c.

101 {
102  Size size = 0;
103  Size TotalProcs =
105 
106  /* ProcGlobal */
107  size = add_size(size, sizeof(PROC_HDR));
108  size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
109  size = add_size(size, sizeof(slock_t));
110 
111  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
112  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
113  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
114 
115  return size;
116 }
size_t Size
Definition: c.h:594
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519

References add_size(), max_prepared_xacts, MaxBackends, mul_size(), NUM_AUXILIARY_PROCS, ProcGlobal, PROC_HDR::statusFlags, PROC_HDR::subxidStates, and PROC_HDR::xids.

Referenced by CalculateShmemSize().

◆ ProcKill()

static void ProcKill ( int  code,
Datum  arg 
)
static

Definition at line 802 of file proc.c.

803 {
804  PGPROC *proc;
805  dlist_head *procgloballist;
806 
807  Assert(MyProc != NULL);
808 
809  /* Make sure we're out of the sync rep lists */
811 
812 #ifdef USE_ASSERT_CHECKING
813  {
814  int i;
815 
816  /* Last process should have released all locks. */
817  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
819  }
820 #endif
821 
822  /*
823  * Release any LW locks I am holding. There really shouldn't be any, but
824  * it's cheap to check again before we cut the knees off the LWLock
825  * facility by releasing our PGPROC ...
826  */
828 
829  /* Cancel any pending condition variable sleep, too */
831 
832  /*
833  * Detach from any lock group of which we are a member. If the leader
834  * exits before all other group members, its PGPROC will remain allocated
835  * until the last group process exits; that process must return the
836  * leader's PGPROC to the appropriate list.
837  */
838  if (MyProc->lockGroupLeader != NULL)
839  {
840  PGPROC *leader = MyProc->lockGroupLeader;
841  LWLock *leader_lwlock = LockHashPartitionLockByProc(leader);
842 
843  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
846  if (dlist_is_empty(&leader->lockGroupMembers))
847  {
848  leader->lockGroupLeader = NULL;
849  if (leader != MyProc)
850  {
851  procgloballist = leader->procgloballist;
852 
853  /* Leader exited first; return its PGPROC. */
855  dlist_push_head(procgloballist, &leader->links);
857  }
858  }
859  else if (leader != MyProc)
860  MyProc->lockGroupLeader = NULL;
861  LWLockRelease(leader_lwlock);
862  }
863 
864  /*
865  * Reset MyLatch to the process local one. This is so that signal
866  * handlers et al can continue using the latch after the shared latch
867  * isn't ours anymore.
868  *
869  * Similarly, stop reporting wait events to MyProc->wait_event_info.
870  *
871  * After that clear MyProc and disown the shared latch.
872  */
875 
876  proc = MyProc;
877  MyProc = NULL;
878  DisownLatch(&proc->procLatch);
879 
880  procgloballist = proc->procgloballist;
882 
883  /*
884  * If we're still a member of a locking group, that means we're a leader
885  * which has somehow exited before its children. The last remaining child
886  * will release our PGPROC. Otherwise, release it now.
887  */
888  if (proc->lockGroupLeader == NULL)
889  {
890  /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
892 
893  /* Return PGPROC structure (and semaphore) to appropriate freelist */
894  dlist_push_tail(procgloballist, &proc->links);
895  }
896 
897  /* Update shared estimate of spins_per_delay */
899 
901 
902  /*
903  * This process is no longer present in shared memory in any meaningful
904  * way, so tell the postmaster we've cleaned up acceptably well. (XXX
905  * autovac launcher should be included here someday)
906  */
909 
910  /* wake autovac launcher if needed -- see comments in FreeWorkerInfo */
911  if (AutovacuumLauncherPid != 0)
913 }
int AutovacuumLauncherPid
Definition: autovacuum.c:316
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
void MarkPostmasterChildInactive(void)
Definition: pmsignal.c:356
void SyncRepCleanupAtProcExit(void)
Definition: syncrep.c:374
#define kill(pid, sig)
Definition: win32_port.h:485
#define SIGUSR2
Definition: win32_port.h:181

References Assert(), AutovacuumLauncherPid, ConditionVariableCancelSleep(), DisownLatch(), dlist_delete(), dlist_is_empty(), dlist_push_head(), dlist_push_tail(), i, IsAutoVacuumLauncherProcess(), IsUnderPostmaster, kill, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupLink, PGPROC::lockGroupMembers, LockHashPartitionLockByProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LWLockReleaseAll(), MarkPostmasterChildInactive(), MyProc, PGPROC::myProcLocks, NUM_LOCK_PARTITIONS, pgstat_reset_wait_event_storage(), ProcGlobal, PGPROC::procgloballist, PGPROC::procLatch, ProcStructLock, SIGUSR2, SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, SwitchBackToLocalLatch(), SyncRepCleanupAtProcExit(), and update_spins_per_delay().

Referenced by InitProcess().

◆ ProcLockWakeup()

void ProcLockWakeup ( LockMethod  lockMethodTable,
LOCK lock 
)

Definition at line 1637 of file proc.c.

1638 {
1639  dclist_head *waitQueue = &lock->waitProcs;
1640  LOCKMASK aheadRequests = 0;
1641  dlist_mutable_iter miter;
1642 
1643  if (dclist_is_empty(waitQueue))
1644  return;
1645 
1646  dclist_foreach_modify(miter, waitQueue)
1647  {
1648  PGPROC *proc = dlist_container(PGPROC, links, miter.cur);
1649  LOCKMODE lockmode = proc->waitLockMode;
1650 
1651  /*
1652  * Waken if (a) doesn't conflict with requests of earlier waiters, and
1653  * (b) doesn't conflict with already-held locks.
1654  */
1655  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1656  !LockCheckConflicts(lockMethodTable, lockmode, lock,
1657  proc->waitProcLock))
1658  {
1659  /* OK to waken */
1660  GrantLock(lock, proc->waitProcLock, lockmode);
1661  /* removes proc from the lock's waiting process queue */
1663  }
1664  else
1665  {
1666  /*
1667  * Lock conflicts: Don't wake, but remember requested mode for
1668  * later checks.
1669  */
1670  aheadRequests |= LOCKBIT_ON(lockmode);
1671  }
1672  }
1673 }
static bool dclist_is_empty(const dclist_head *head)
Definition: ilist.h:682
#define dclist_foreach_modify(iter, lhead)
Definition: ilist.h:973
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1526
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1397
#define LOCKBIT_ON(lockmode)
Definition: lock.h:84
int LOCKMODE
Definition: lockdefs.h:26
int LOCKMASK
Definition: lockdefs.h:25
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition: proc.c:1609
dclist_head waitProcs
Definition: lock.h:317
const LOCKMASK * conflictTab
Definition: lock.h:111
LOCKMODE waitLockMode
Definition: proc.h:225
dlist_node * cur
Definition: ilist.h:200
static struct link * links
Definition: zic.c:299

References LockMethodData::conflictTab, dlist_mutable_iter::cur, dclist_foreach_modify, dclist_is_empty(), dlist_container, GrantLock(), links, LOCKBIT_ON, LockCheckConflicts(), PROC_WAIT_STATUS_OK, ProcWakeup(), PGPROC::waitLockMode, PGPROC::waitProcLock, and LOCK::waitProcs.

Referenced by CleanUpLock(), and DeadLockCheck().

◆ ProcReleaseLocks()

void ProcReleaseLocks ( bool  isCommit)

Definition at line 774 of file proc.c.

775 {
776  if (!MyProc)
777  return;
778  /* If waiting, get off wait queue (should only be needed after error) */
780  /* Release standard locks, including session-level if aborting */
782  /* Release transaction-level advisory locks */
784 }
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2130
#define DEFAULT_LOCKMETHOD
Definition: lock.h:125
#define USER_LOCKMETHOD
Definition: lock.h:126
void LockErrorCleanup(void)
Definition: proc.c:698

References DEFAULT_LOCKMETHOD, LockErrorCleanup(), LockReleaseAll(), MyProc, and USER_LOCKMETHOD.

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( int  pgprocno)

Definition at line 1809 of file proc.c.

1810 {
1811  if (pgprocno < 0 || pgprocno >= ProcGlobal->allProcCount)
1812  elog(ERROR, "pgprocno out of range");
1813 
1814  SetLatch(&ProcGlobal->allProcs[pgprocno].procLatch);
1815 }

References PROC_HDR::allProcCount, PROC_HDR::allProcs, elog(), ERROR, ProcGlobal, PGPROC::procLatch, and SetLatch().

Referenced by ReleasePredicateLocks(), and UnpinBuffer().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock,
LockMethod  lockMethodTable 
)

Definition at line 1004 of file proc.c.

1005 {
1006  LOCKMODE lockmode = locallock->tag.mode;
1007  LOCK *lock = locallock->lock;
1008  PROCLOCK *proclock = locallock->proclock;
1009  uint32 hashcode = locallock->hashcode;
1010  LWLock *partitionLock = LockHashPartitionLock(hashcode);
1011  dclist_head *waitQueue = &lock->waitProcs;
1012  PGPROC *insert_before = NULL;
1013  LOCKMASK myHeldLocks = MyProc->heldLocks;
1014  TimestampTz standbyWaitStart = 0;
1015  bool early_deadlock = false;
1016  bool allow_autovacuum_cancel = true;
1017  bool logged_recovery_conflict = false;
1018  ProcWaitStatus myWaitStatus;
1019  PGPROC *leader = MyProc->lockGroupLeader;
1020 
1021  /*
1022  * If group locking is in use, locks held by members of my locking group
1023  * need to be included in myHeldLocks. This is not required for relation
1024  * extension lock which conflict among group members. However, including
1025  * them in myHeldLocks will give group members the priority to get those
1026  * locks as compared to other backends which are also trying to acquire
1027  * those locks. OTOH, we can avoid giving priority to group members for
1028  * that kind of locks, but there doesn't appear to be a clear advantage of
1029  * the same.
1030  */
1031  if (leader != NULL)
1032  {
1033  dlist_iter iter;
1034 
1035  dlist_foreach(iter, &lock->procLocks)
1036  {
1037  PROCLOCK *otherproclock;
1038 
1039  otherproclock = dlist_container(PROCLOCK, lockLink, iter.cur);
1040 
1041  if (otherproclock->groupLeader == leader)
1042  myHeldLocks |= otherproclock->holdMask;
1043  }
1044  }
1045 
1046  /*
1047  * Determine where to add myself in the wait queue.
1048  *
1049  * Normally I should go at the end of the queue. However, if I already
1050  * hold locks that conflict with the request of any previous waiter, put
1051  * myself in the queue just in front of the first such waiter. This is not
1052  * a necessary step, since deadlock detection would move me to before that
1053  * waiter anyway; but it's relatively cheap to detect such a conflict
1054  * immediately, and avoid delaying till deadlock timeout.
1055  *
1056  * Special case: if I find I should go in front of some waiter, check to
1057  * see if I conflict with already-held locks or the requests before that
1058  * waiter. If not, then just grant myself the requested lock immediately.
1059  * This is the same as the test for immediate grant in LockAcquire, except
1060  * we are only considering the part of the wait queue before my insertion
1061  * point.
1062  */
1063  if (myHeldLocks != 0 && !dclist_is_empty(waitQueue))
1064  {
1065  LOCKMASK aheadRequests = 0;
1066  dlist_iter iter;
1067 
1068  dclist_foreach(iter, waitQueue)
1069  {
1070  PGPROC *proc = dlist_container(PGPROC, links, iter.cur);
1071 
1072  /*
1073  * If we're part of the same locking group as this waiter, its
1074  * locks neither conflict with ours nor contribute to
1075  * aheadRequests.
1076  */
1077  if (leader != NULL && leader == proc->lockGroupLeader)
1078  continue;
1079 
1080  /* Must he wait for me? */
1081  if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
1082  {
1083  /* Must I wait for him ? */
1084  if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
1085  {
1086  /*
1087  * Yes, so we have a deadlock. Easiest way to clean up
1088  * correctly is to call RemoveFromWaitQueue(), but we
1089  * can't do that until we are *on* the wait queue. So, set
1090  * a flag to check below, and break out of loop. Also,
1091  * record deadlock info for later message.
1092  */
1093  RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
1094  early_deadlock = true;
1095  break;
1096  }
1097  /* I must go before this waiter. Check special case. */
1098  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1099  !LockCheckConflicts(lockMethodTable, lockmode, lock,
1100  proclock))
1101  {
1102  /* Skip the wait and just grant myself the lock. */
1103  GrantLock(lock, proclock, lockmode);
1104  GrantAwaitedLock();
1105  return PROC_WAIT_STATUS_OK;
1106  }
1107 
1108  /* Put myself into wait queue before conflicting process */
1109  insert_before = proc;
1110  break;
1111  }
1112  /* Nope, so advance to next waiter */
1113  aheadRequests |= LOCKBIT_ON(proc->waitLockMode);
1114  }
1115  }
1116 
1117  /*
1118  * Insert self into queue, at the position determined above.
1119  */
1120  if (insert_before)
1121  dclist_insert_before(waitQueue, &insert_before->links, &MyProc->links);
1122  else
1123  dclist_push_tail(waitQueue, &MyProc->links);
1124 
1125  lock->waitMask |= LOCKBIT_ON(lockmode);
1126 
1127  /* Set up wait information in PGPROC object, too */
1128  MyProc->waitLock = lock;
1129  MyProc->waitProcLock = proclock;
1130  MyProc->waitLockMode = lockmode;
1131 
1133 
1134  /*
1135  * If we detected deadlock, give up without waiting. This must agree with
1136  * CheckDeadLock's recovery code.
1137  */
1138  if (early_deadlock)
1139  {
1140  RemoveFromWaitQueue(MyProc, hashcode);
1141  return PROC_WAIT_STATUS_ERROR;
1142  }
1143 
1144  /* mark that we are waiting for a lock */
1145  lockAwaited = locallock;
1146 
1147  /*
1148  * Release the lock table's partition lock.
1149  *
1150  * NOTE: this may also cause us to exit critical-section state, possibly
1151  * allowing a cancel/die interrupt to be accepted. This is OK because we
1152  * have recorded the fact that we are waiting for a lock, and so
1153  * LockErrorCleanup will clean up if cancel/die happens.
1154  */
1155  LWLockRelease(partitionLock);
1156 
1157  /*
1158  * Also, now that we will successfully clean up after an ereport, it's
1159  * safe to check to see if there's a buffer pin deadlock against the
1160  * Startup process. Of course, that's only necessary if we're doing Hot
1161  * Standby and are not the Startup process ourselves.
1162  */
1163  if (RecoveryInProgress() && !InRecovery)
1165 
1166  /* Reset deadlock_state before enabling the timeout handler */
1168  got_deadlock_timeout = false;
1169 
1170  /*
1171  * Set timer so we can wake up after awhile and check for a deadlock. If a
1172  * deadlock is detected, the handler sets MyProc->waitStatus =
1173  * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
1174  * rather than success.
1175  *
1176  * By delaying the check until we've waited for a bit, we can avoid
1177  * running the rather expensive deadlock-check code in most cases.
1178  *
1179  * If LockTimeout is set, also enable the timeout for that. We can save a
1180  * few cycles by enabling both timeout sources in one call.
1181  *
1182  * If InHotStandby we set lock waits slightly later for clarity with other
1183  * code.
1184  */
1185  if (!InHotStandby)
1186  {
1187  if (LockTimeout > 0)
1188  {
1189  EnableTimeoutParams timeouts[2];
1190 
1191  timeouts[0].id = DEADLOCK_TIMEOUT;
1192  timeouts[0].type = TMPARAM_AFTER;
1193  timeouts[0].delay_ms = DeadlockTimeout;
1194  timeouts[1].id = LOCK_TIMEOUT;
1195  timeouts[1].type = TMPARAM_AFTER;
1196  timeouts[1].delay_ms = LockTimeout;
1197  enable_timeouts(timeouts, 2);
1198  }
1199  else
1201 
1202  /*
1203  * Use the current time obtained for the deadlock timeout timer as
1204  * waitStart (i.e., the time when this process started waiting for the
1205  * lock). Since getting the current time newly can cause overhead, we
1206  * reuse the already-obtained time to avoid that overhead.
1207  *
1208  * Note that waitStart is updated without holding the lock table's
1209  * partition lock, to avoid the overhead by additional lock
1210  * acquisition. This can cause "waitstart" in pg_locks to become NULL
1211  * for a very short period of time after the wait started even though
1212  * "granted" is false. This is OK in practice because we can assume
1213  * that users are likely to look at "waitstart" when waiting for the
1214  * lock for a long time.
1215  */
1218  }
1219  else if (log_recovery_conflict_waits)
1220  {
1221  /*
1222  * Set the wait start timestamp if logging is enabled and in hot
1223  * standby.
1224  */
1225  standbyWaitStart = GetCurrentTimestamp();
1226  }
1227 
1228  /*
1229  * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1230  * will not wait. But a set latch does not necessarily mean that the lock
1231  * is free now, as there are many other sources for latch sets than
1232  * somebody releasing the lock.
1233  *
1234  * We process interrupts whenever the latch has been set, so cancel/die
1235  * interrupts are processed quickly. This means we must not mind losing
1236  * control to a cancel/die interrupt here. We don't, because we have no
1237  * shared-state-change work to do after being granted the lock (the
1238  * grantor did it all). We do have to worry about canceling the deadlock
1239  * timeout and updating the locallock table, but if we lose control to an
1240  * error, LockErrorCleanup will fix that up.
1241  */
1242  do
1243  {
1244  if (InHotStandby)
1245  {
1246  bool maybe_log_conflict =
1247  (standbyWaitStart != 0 && !logged_recovery_conflict);
1248 
1249  /* Set a timer and wait for that or for the lock to be granted */
1251  maybe_log_conflict);
1252 
1253  /*
1254  * Emit the log message if the startup process is waiting longer
1255  * than deadlock_timeout for recovery conflict on lock.
1256  */
1257  if (maybe_log_conflict)
1258  {
1260 
1261  if (TimestampDifferenceExceeds(standbyWaitStart, now,
1262  DeadlockTimeout))
1263  {
1264  VirtualTransactionId *vxids;
1265  int cnt;
1266 
1267  vxids = GetLockConflicts(&locallock->tag.lock,
1268  AccessExclusiveLock, &cnt);
1269 
1270  /*
1271  * Log the recovery conflict and the list of PIDs of
1272  * backends holding the conflicting lock. Note that we do
1273  * logging even if there are no such backends right now
1274  * because the startup process here has already waited
1275  * longer than deadlock_timeout.
1276  */
1278  standbyWaitStart, now,
1279  cnt > 0 ? vxids : NULL, true);
1280  logged_recovery_conflict = true;
1281  }
1282  }
1283  }
1284  else
1285  {
1287  PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1289  /* check for deadlocks first, as that's probably log-worthy */
1291  {
1292  CheckDeadLock();
1293  got_deadlock_timeout = false;
1294  }
1296  }
1297 
1298  /*
1299  * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
1300  * else asynchronously. Read it just once per loop to prevent
1301  * surprising behavior (such as missing log messages).
1302  */
1303  myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
1304 
1305  /*
1306  * If we are not deadlocked, but are waiting on an autovacuum-induced
1307  * task, send a signal to interrupt it.
1308  */
1309  if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
1310  {
1311  PGPROC *autovac = GetBlockingAutoVacuumPgproc();
1312  uint8 statusFlags;
1313  uint8 lockmethod_copy;
1314  LOCKTAG locktag_copy;
1315 
1316  /*
1317  * Grab info we need, then release lock immediately. Note this
1318  * coding means that there is a tiny chance that the process
1319  * terminates its current transaction and starts a different one
1320  * before we have a change to send the signal; the worst possible
1321  * consequence is that a for-wraparound vacuum is cancelled. But
1322  * that could happen in any case unless we were to do kill() with
1323  * the lock held, which is much more undesirable.
1324  */
1325  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1326  statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1327  lockmethod_copy = lock->tag.locktag_lockmethodid;
1328  locktag_copy = lock->tag;
1329  LWLockRelease(ProcArrayLock);
1330 
1331  /*
1332  * Only do it if the worker is not working to protect against Xid
1333  * wraparound.
1334  */
1335  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
1336  !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
1337  {
1338  int pid = autovac->pid;
1339 
1340  /* report the case, if configured to do so */
1342  {
1343  StringInfoData locktagbuf;
1344  StringInfoData logbuf; /* errdetail for server log */
1345 
1346  initStringInfo(&locktagbuf);
1347  initStringInfo(&logbuf);
1348  DescribeLockTag(&locktagbuf, &locktag_copy);
1349  appendStringInfo(&logbuf,
1350  "Process %d waits for %s on %s.",
1351  MyProcPid,
1352  GetLockmodeName(lockmethod_copy, lockmode),
1353  locktagbuf.data);
1354 
1355  ereport(DEBUG1,
1356  (errmsg_internal("sending cancel to blocking autovacuum PID %d",
1357  pid),
1358  errdetail_log("%s", logbuf.data)));
1359 
1360  pfree(locktagbuf.data);
1361  pfree(logbuf.data);
1362  }
1363 
1364  /* send the autovacuum worker Back to Old Kent Road */
1365  if (kill(pid, SIGINT) < 0)
1366  {
1367  /*
1368  * There's a race condition here: once we release the
1369  * ProcArrayLock, it's possible for the autovac worker to
1370  * close up shop and exit before we can do the kill().
1371  * Therefore, we do not whinge about no-such-process.
1372  * Other errors such as EPERM could conceivably happen if
1373  * the kernel recycles the PID fast enough, but such cases
1374  * seem improbable enough that it's probably best to issue
1375  * a warning if we see some other errno.
1376  */
1377  if (errno != ESRCH)
1378  ereport(WARNING,
1379  (errmsg("could not send signal to process %d: %m",
1380  pid)));
1381  }
1382  }
1383 
1384  /* prevent signal from being sent again more than once */
1385  allow_autovacuum_cancel = false;
1386  }
1387 
1388  /*
1389  * If awoken after the deadlock check interrupt has run, and
1390  * log_lock_waits is on, then report about the wait.
1391  */
1393  {
1395  lock_waiters_sbuf,
1396  lock_holders_sbuf;
1397  const char *modename;
1398  long secs;
1399  int usecs;
1400  long msecs;
1401  dlist_iter proc_iter;
1402  PROCLOCK *curproclock;
1403  bool first_holder = true,
1404  first_waiter = true;
1405  int lockHoldersNum = 0;
1406 
1407  initStringInfo(&buf);
1408  initStringInfo(&lock_waiters_sbuf);
1409  initStringInfo(&lock_holders_sbuf);
1410 
1411  DescribeLockTag(&buf, &locallock->tag.lock);
1412  modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1413  lockmode);
1416  &secs, &usecs);
1417  msecs = secs * 1000 + usecs / 1000;
1418  usecs = usecs % 1000;
1419 
1420  /*
1421  * we loop over the lock's procLocks to gather a list of all
1422  * holders and waiters. Thus we will be able to provide more
1423  * detailed information for lock debugging purposes.
1424  *
1425  * lock->procLocks contains all processes which hold or wait for
1426  * this lock.
1427  */
1428 
1429  LWLockAcquire(partitionLock, LW_SHARED);
1430 
1431  dlist_foreach(proc_iter, &lock->procLocks)
1432  {
1433  curproclock =
1434  dlist_container(PROCLOCK, lockLink, proc_iter.cur);
1435 
1436  /*
1437  * we are a waiter if myProc->waitProcLock == curproclock; we
1438  * are a holder if it is NULL or something different
1439  */
1440  if (curproclock->tag.myProc->waitProcLock == curproclock)
1441  {
1442  if (first_waiter)
1443  {
1444  appendStringInfo(&lock_waiters_sbuf, "%d",
1445  curproclock->tag.myProc->pid);
1446  first_waiter = false;
1447  }
1448  else
1449  appendStringInfo(&lock_waiters_sbuf, ", %d",
1450  curproclock->tag.myProc->pid);
1451  }
1452  else
1453  {
1454  if (first_holder)
1455  {
1456  appendStringInfo(&lock_holders_sbuf, "%d",
1457  curproclock->tag.myProc->pid);
1458  first_holder = false;
1459  }
1460  else
1461  appendStringInfo(&lock_holders_sbuf, ", %d",
1462  curproclock->tag.myProc->pid);
1463 
1464  lockHoldersNum++;
1465  }
1466  }
1467 
1468  LWLockRelease(partitionLock);
1469 
1471  ereport(LOG,
1472  (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1473  MyProcPid, modename, buf.data, msecs, usecs),
1474  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1475  "Processes holding the lock: %s. Wait queue: %s.",
1476  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1477  else if (deadlock_state == DS_HARD_DEADLOCK)
1478  {
1479  /*
1480  * This message is a bit redundant with the error that will be
1481  * reported subsequently, but in some cases the error report
1482  * might not make it to the log (eg, if it's caught by an
1483  * exception handler), and we want to ensure all long-wait
1484  * events get logged.
1485  */
1486  ereport(LOG,
1487  (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1488  MyProcPid, modename, buf.data, msecs, usecs),
1489  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1490  "Processes holding the lock: %s. Wait queue: %s.",
1491  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1492  }
1493 
1494  if (myWaitStatus == PROC_WAIT_STATUS_WAITING)
1495  ereport(LOG,
1496  (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1497  MyProcPid, modename, buf.data, msecs, usecs),
1498  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1499  "Processes holding the lock: %s. Wait queue: %s.",
1500  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1501  else if (myWaitStatus == PROC_WAIT_STATUS_OK)
1502  ereport(LOG,
1503  (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1504  MyProcPid, modename, buf.data, msecs, usecs)));
1505  else
1506  {
1507  Assert(myWaitStatus == PROC_WAIT_STATUS_ERROR);
1508 
1509  /*
1510  * Currently, the deadlock checker always kicks its own
1511  * process, which means that we'll only see
1512  * PROC_WAIT_STATUS_ERROR when deadlock_state ==
1513  * DS_HARD_DEADLOCK, and there's no need to print redundant
1514  * messages. But for completeness and future-proofing, print
1515  * a message if it looks like someone else kicked us off the
1516  * lock.
1517  */
1519  ereport(LOG,
1520  (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1521  MyProcPid, modename, buf.data, msecs, usecs),
1522  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1523  "Processes holding the lock: %s. Wait queue: %s.",
1524  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1525  }
1526 
1527  /*
1528  * At this point we might still need to wait for the lock. Reset
1529  * state so we don't print the above messages again.
1530  */
1532 
1533  pfree(buf.data);
1534  pfree(lock_holders_sbuf.data);
1535  pfree(lock_waiters_sbuf.data);
1536  }
1537  } while (myWaitStatus == PROC_WAIT_STATUS_WAITING);
1538 
1539  /*
1540  * Disable the timers, if they are still running. As in LockErrorCleanup,
1541  * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1542  * already caused QueryCancelPending to become set, we want the cancel to
1543  * be reported as a lock timeout, not a user cancel.
1544  */
1545  if (!InHotStandby)
1546  {
1547  if (LockTimeout > 0)
1548  {
1549  DisableTimeoutParams timeouts[2];
1550 
1551  timeouts[0].id = DEADLOCK_TIMEOUT;
1552  timeouts[0].keep_indicator = false;
1553  timeouts[1].id = LOCK_TIMEOUT;
1554  timeouts[1].keep_indicator = true;
1555  disable_timeouts(timeouts, 2);
1556  }
1557  else
1559  }
1560 
1561  /*
1562  * Emit the log message if recovery conflict on lock was resolved but the
1563  * startup process waited longer than deadlock_timeout for it.
1564  */
1565  if (InHotStandby && logged_recovery_conflict)
1567  standbyWaitStart, GetCurrentTimestamp(),
1568  NULL, false);
1569 
1570  /*
1571  * Re-acquire the lock table's partition lock. We have to do this to hold
1572  * off cancel/die interrupts before we can mess with lockAwaited (else we
1573  * might have a missed or duplicated locallock update).
1574  */
1575  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
1576 
1577  /*
1578  * We no longer want LockErrorCleanup to do anything.
1579  */
1580  lockAwaited = NULL;
1581 
1582  /*
1583  * If we got the lock, be sure to remember it in the locallock table.
1584  */
1586  GrantAwaitedLock();
1587 
1588  /*
1589  * We don't have to do anything else, because the awaker did all the
1590  * necessary update of the lock table and MyProc.
1591  */
1592  return MyProc->waitStatus;
1593 }
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1659
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1719
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1583
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1547
int64 TimestampTz
Definition: timestamp.h:39
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition: deadlock.c:287
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition: deadlock.c:1144
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
bool message_level_is_interesting(int elevel)
Definition: elog.c:277
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1271
int errdetail_log(const char *fmt,...)
Definition: elog.c:1250
#define LOG
Definition: elog.h:31
#define WARNING
Definition: elog.h:36
#define DEBUG1
Definition: elog.h:30
static void dclist_push_tail(dclist_head *head, dlist_node *node)
Definition: ilist.h:709
static void dclist_insert_before(dclist_head *head, dlist_node *before, dlist_node *node)
Definition: ilist.h:745
#define dclist_foreach(iter, lhead)
Definition: ilist.h:970
void ResetLatch(Latch *latch)
Definition: latch.c:697
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:490
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:130
#define WL_LATCH_SET
Definition: latch.h:125
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1168
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition: lock.c:2855
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:4021
@ DS_BLOCKED_BY_AUTOVACUUM
Definition: lock.h:515
@ DS_NO_DEADLOCK
Definition: lock.h:512
@ DS_NOT_YET_CHECKED
Definition: lock.h:511
@ DS_SOFT_DEADLOCK
Definition: lock.h:513
#define AccessExclusiveLock
Definition: lockdefs.h:43
@ LW_SHARED
Definition: lwlock.h:117
void pfree(void *pointer)
Definition: mcxt.c:1456
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
static char * buf
Definition: pg_test_fsync.c:67
#define PROC_VACUUM_FOR_WRAPAROUND
Definition: proc.h:59
ProcWaitStatus
Definition: proc.h:123
@ PROC_WAIT_STATUS_WAITING
Definition: proc.h:125
@ PROC_WAIT_STATUS_ERROR
Definition: proc.h:126
@ PROCSIG_RECOVERY_CONFLICT_LOCK
Definition: procsignal.h:44
bool log_lock_waits
Definition: proc.c:63
int DeadlockTimeout
Definition: proc.c:58
static void CheckDeadLock(void)
Definition: proc.c:1685
int LockTimeout
Definition: proc.c:60
void CheckRecoveryConflictDeadlock(void)
Definition: standby.c:905
bool log_recovery_conflict_waits
Definition: standby.c:43
void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition: standby.c:274
void ResolveRecoveryConflictWithLock(LOCKTAG locktag, bool logging_conflict)
Definition: standby.c:623
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
TimeoutType type
Definition: timeout.h:60
TimeoutId id
Definition: timeout.h:59
LOCKTAG lock
Definition: lock.h:410
LOCKMODE mode
Definition: lock.h:411
LOCK * lock
Definition: lock.h:433
PROCLOCK * proclock
Definition: lock.h:434
LOCALLOCKTAG tag
Definition: lock.h:429
Definition: lock.h:165
uint8 locktag_type
Definition: lock.h:170
uint8 locktag_lockmethodid
Definition: lock.h:171
Definition: lock.h:309
LOCKMASK waitMask
Definition: lock.h:315
dlist_head procLocks
Definition: lock.h:316
int pgxactoff
Definition: proc.h:188
LOCKMASK heldLocks
Definition: proc.h:226
PGPROC * myProc
Definition: lock.h:366
Definition: lock.h:370
LOCKMASK holdMask
Definition: lock.h:376
PGPROC * groupLeader
Definition: lock.h:375
PROCLOCKTAG tag
Definition: lock.h:372
dlist_node * cur
Definition: ilist.h:179
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:564
TimestampTz get_timeout_start_time(TimeoutId id)
Definition: timeout.c:817
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:689
void enable_timeouts(const EnableTimeoutParams *timeouts, int count)
Definition: timeout.c:634
@ TMPARAM_AFTER
Definition: timeout.h:52
#define PG_WAIT_LOCK
Definition: wait_event.h:19
bool RecoveryInProgress(void)
Definition: xlog.c:5948
bool InRecovery
Definition: xlogutils.c:53
#define InHotStandby
Definition: xlogutils.h:57

References AccessExclusiveLock, appendStringInfo(), Assert(), buf, CHECK_FOR_INTERRUPTS, CheckDeadLock(), CheckRecoveryConflictDeadlock(), LockMethodData::conflictTab, dlist_iter::cur, StringInfoData::data, dclist_foreach, dclist_insert_before(), dclist_is_empty(), dclist_push_tail(), deadlock_state, DEADLOCK_TIMEOUT, DeadlockTimeout, DEBUG1, EnableTimeoutParams::delay_ms, DescribeLockTag(), disable_timeout(), disable_timeouts(), dlist_container, dlist_foreach, DS_BLOCKED_BY_AUTOVACUUM, DS_HARD_DEADLOCK, DS_NO_DEADLOCK, DS_NOT_YET_CHECKED, DS_SOFT_DEADLOCK, enable_timeout_after(), enable_timeouts(), ereport, errdetail_log(), errdetail_log_plural(), errmsg(), errmsg_internal(), get_timeout_start_time(), GetBlockingAutoVacuumPgproc(), GetCurrentTimestamp(), GetLockConflicts(), GetLockmodeName(), got_deadlock_timeout, GrantAwaitedLock(), GrantLock(), PROCLOCK::groupLeader, LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, EnableTimeoutParams::id, DisableTimeoutParams::id, InHotStandby, initStringInfo(), InRecovery, DisableTimeoutParams::keep_indicator, kill, PGPROC::links, links, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_TIMEOUT, lockAwaited, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, LOCKTAG::locktag_lockmethodid, LOCKTAG::locktag_type, LockTimeout, LOG, log_lock_waits, log_recovery_conflict_waits, LogRecoveryConflict(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), message_level_is_interesting(), LOCALLOCKTAG::mode, MyLatch, MyProc, PROCLOCKTAG::myProc, MyProcPid, now(), pfree(), pg_atomic_write_u64(), PG_WAIT_LOCK, PGPROC::pgxactoff, PGPROC::pid, PROC_IS_AUTOVACUUM, PROC_VACUUM_FOR_WRAPAROUND, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_OK, PROC_WAIT_STATUS_WAITING, ProcGlobal, LOCALLOCK::proclock, LOCK::procLocks, PROCSIG_RECOVERY_CONFLICT_LOCK, RecoveryInProgress(), RememberSimpleDeadLock(), RemoveFromWaitQueue(), ResetLatch(), ResolveRecoveryConflictWithLock(), PROC_HDR::statusFlags, LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, TimestampDifference(), TimestampDifferenceExceeds(), TMPARAM_AFTER, EnableTimeoutParams::type, WaitLatch(), PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, PGPROC::waitStart, PGPROC::waitStatus, WARNING, WL_EXIT_ON_PM_DEATH, and WL_LATCH_SET.

Referenced by WaitOnLock().

◆ ProcWaitForSignal()

void ProcWaitForSignal ( uint32  wait_event_info)

◆ ProcWakeup()

void ProcWakeup ( PGPROC proc,
ProcWaitStatus  waitStatus 
)

Definition at line 1609 of file proc.c.

1610 {
1611  if (dlist_node_is_detached(&proc->links))
1612  return;
1613 
1615 
1616  /* Remove process from wait queue */
1618 
1619  /* Clean up process' state and pass it the ok/fail signal */
1620  proc->waitLock = NULL;
1621  proc->waitProcLock = NULL;
1622  proc->waitStatus = waitStatus;
1624 
1625  /* And awaken it */
1626  SetLatch(&proc->procLatch);
1627 }
static void dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node)
Definition: ilist.h:776

References Assert(), dclist_delete_from_thoroughly(), dlist_node_is_detached(), PGPROC::links, MyProc, pg_atomic_write_u64(), PROC_WAIT_STATUS_WAITING, PGPROC::procLatch, SetLatch(), PGPROC::waitLock, PGPROC::waitProcLock, LOCK::waitProcs, PGPROC::waitStart, and PGPROC::waitStatus.

Referenced by ProcLockWakeup().

◆ RemoveProcFromArray()

static void RemoveProcFromArray ( int  code,
Datum  arg 
)
static

Definition at line 791 of file proc.c.

792 {
793  Assert(MyProc != NULL);
795 }
void ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:565

References Assert(), InvalidTransactionId, MyProc, and ProcArrayRemove().

Referenced by InitProcessPhase2().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 627 of file proc.c.

628 {
629  /* use volatile pointer to prevent code rearrangement */
630  volatile PROC_HDR *procglobal = ProcGlobal;
631 
632  procglobal->startupBufferPinWaitBufId = bufid;
633 }

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

Variable Documentation

◆ AuxiliaryProcs

NON_EXEC_STATIC PGPROC* AuxiliaryProcs = NULL

◆ deadlock_state

DeadLockState deadlock_state = DS_NOT_YET_CHECKED
static

Definition at line 85 of file proc.c.

Referenced by CheckDeadLock(), and ProcSleep().

◆ DeadlockTimeout

◆ got_deadlock_timeout

volatile sig_atomic_t got_deadlock_timeout
static

Definition at line 88 of file proc.c.

Referenced by CheckDeadLockAlert(), and ProcSleep().

◆ IdleInTransactionSessionTimeout

int IdleInTransactionSessionTimeout = 0

Definition at line 61 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

int IdleSessionTimeout = 0

Definition at line 62 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ lockAwaited

LOCALLOCK* lockAwaited = NULL
static

Definition at line 83 of file proc.c.

Referenced by IsWaitingForLock(), LockErrorCleanup(), and ProcSleep().

◆ LockTimeout

int LockTimeout = 0

Definition at line 60 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

bool log_lock_waits = false

Definition at line 63 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGPROC* MyProc = NULL

Definition at line 66 of file proc.c.

Referenced by _bt_parallel_build_main(), AbortTransaction(), AtEOSubXact_Namespace(), AtEOXact_Namespace(), AtEOXact_Snapshot(), attach_to_queues(), AutoVacWorkerMain(), AuxiliaryProcKill(), BackgroundWriterMain(), BaseInit(), BecomeLockGroupLeader(), BecomeLockGroupMember(), CheckDeadLock(), CheckpointerMain(), CommitTransaction(), ComputeXidHorizons(), ConditionVariableBroadcast(), ConditionVariableCancelSleep(), ConditionVariablePrepareToSleep(), ConditionVariableTimedSleep(), CountOtherDBBackends(), CreateReplicationSlot(), DefineIndex(), EndPrepare(), errdetail_abort(), exec_eval_simple_expr(), exec_simple_check_plan(), exec_stmt_call(), ExecParallelGetReceiver(), ExecParallelSetupTupleQueues(), ExportSnapshot(), FastPathGetRelationLockEntry(), FastPathGrantRelationLock(), FastPathUnGrantRelationLock(), FindLockCycleRecurseMember(), fmgr_sql(), get_cast_hashentry(), GetCurrentVirtualXIDs(), GetLockConflicts(), GetNewTransactionId(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), GetSnapshotDataReuse(), GetStableLatestTransactionId(), init_sql_fcache(), InitAuxiliaryProcess(), InitBufferPoolAccess(), InitializeParallelDSM(), InitializeSessionUserId(), InitPostgres(), InitProcess(), InitProcessPhase2(), InitTempTableNamespace(), InitWalSenderSlot(), lock_and_open_sequence(), LockAcquireExtended(), LockBufferForCleanup(), LockCheckConflicts(), LockErrorCleanup(), LockRelease(), LockReleaseAll(), log_status_format(), logicalrep_worker_attach(), LWLockAcquire(), LWLockAcquireOrWait(), LWLockAttemptLock(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockWaitForVar(), MarkAsPreparingGuts(), MarkBufferDirtyHint(), MinimumActiveBackends(), pa_setup_dsm(), parallel_vacuum_main(), ParallelApplyWorkerMain(), ParallelWorkerMain(), PgArchiverMain(), pgstat_report_activity(), PhysicalReplicationSlotNewXmin(), PostPrepare_Locks(), PrepareTransaction(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcessRecoveryConflictInterrupt(), ProcessStandbyHSFeedbackMessage(), ProcKill(), ProcReleaseLocks(), ProcSleep(), ProcWakeup(), RecordTransactionCommit(), RecordTransactionCommitPrepared(), ReinitializeParallelDSM(), RelationTruncate(), RemoveProcFromArray(), ReplicationSlotRelease(), ResolveRecoveryConflictWithLock(), set_indexsafe_procflags(), setup_dynamic_shared_memory(), SharedInvalBackendInit(), shm_mq_attach(), shm_mq_detach_internal(), shm_mq_receive(), shm_mq_sendv(), shm_mq_wait_for_attach(), SnapBuildInitialSnapshot(), SnapshotResetXmin(), StartTransaction(), StartupDecodingContext(), SwitchBackToLocalLatch(), SwitchToSharedLatch(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepQueueInsert(), SyncRepWaitForLSN(), TerminateOtherDBBackends(), TransactionGroupUpdateXidStatus(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), TruncateMultiXact(), UnlockBuffers(), vacuum_rel(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), WaitXLogInsertionsToFinish(), WALInsertLockAcquire(), WalReceiverMain(), WalWriterMain(), write_csvlog(), write_jsonlog(), XidCacheRemoveRunningXids(), and XLogSaveBufferForHint().

◆ PreparedXactProcs

PGPROC* PreparedXactProcs = NULL

Definition at line 80 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ ProcStructLock

NON_EXEC_STATIC slock_t* ProcStructLock = NULL

◆ StatementTimeout

int StatementTimeout = 0

Definition at line 59 of file proc.c.

Referenced by enable_statement_timeout().