PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 "access/xlogwait.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "replication/slotsync.h"
#include "replication/syncrep.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)
 
static Size PGProcShmemSize (void)
 
static Size FastPathLockShmemSize (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)
 
void LockErrorCleanup (void)
 
void ProcReleaseLocks (bool isCommit)
 
PGPROCAuxiliaryPidGetProc (int pid)
 
ProcWaitStatus JoinWaitQueue (LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait)
 
ProcWaitStatus ProcSleep (LOCALLOCK *locallock)
 
void ProcWakeup (PGPROC *proc, ProcWaitStatus waitStatus)
 
void ProcLockWakeup (LockMethod lockMethodTable, LOCK *lock)
 
void CheckDeadLockAlert (void)
 
void GetLockHoldersAndWaiters (LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
 
void ProcWaitForSignal (uint32 wait_event_info)
 
void ProcSendSignal (ProcNumber procNumber)
 
void BecomeLockGroupLeader (void)
 
bool BecomeLockGroupMember (PGPROC *leader, int pid)
 

Variables

int DeadlockTimeout = 1000
 
int StatementTimeout = 0
 
int LockTimeout = 0
 
int IdleInTransactionSessionTimeout = 0
 
int TransactionTimeout = 0
 
int IdleSessionTimeout = 0
 
bool log_lock_waits = true
 
PGPROCMyProc = NULL
 
NON_EXEC_STATIC slock_tProcStructLock = NULL
 
PROC_HDRProcGlobal = NULL
 
NON_EXEC_STATIC PGPROCAuxiliaryProcs = NULL
 
PGPROCPreparedXactProcs = 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 1096 of file proc.c.

1097{
1098 PGPROC *result = NULL;
1099 int index;
1100
1101 if (pid == 0) /* never match dummy PGPROCs */
1102 return NULL;
1103
1104 for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1105 {
1106 PGPROC *proc = &AuxiliaryProcs[index];
1107
1108 if (proc->pid == pid)
1109 {
1110 result = proc;
1111 break;
1112 }
1113 }
1114 return result;
1115}
static int fb(int x)
#define NUM_AUXILIARY_PROCS
Definition proc.h:463
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition proc.c:80
Definition proc.h:180
int pid
Definition proc.h:200
Definition type.h:96

References AuxiliaryProcs, fb(), NUM_AUXILIARY_PROCS, and PGPROC::pid.

Referenced by pg_log_backend_memory_contexts(), pg_stat_get_activity(), pg_stat_reset_backend_stats(), and pgstat_fetch_stat_backend_by_pid().

◆ AuxiliaryProcKill()

static void AuxiliaryProcKill ( int  code,
Datum  arg 
)
static

Definition at line 1045 of file proc.c.

1046{
1047 int proctype = DatumGetInt32(arg);
1049 PGPROC *proc;
1050
1052
1053 /* not safe if forked by system(), etc. */
1054 if (MyProc->pid != (int) getpid())
1055 elog(PANIC, "AuxiliaryProcKill() called in child process");
1056
1058
1059 Assert(MyProc == auxproc);
1060
1061 /* Release any LW locks I am holding (see notes above) */
1063
1064 /* Cancel any pending condition variable sleep, too */
1066
1067 /* look at the equivalent ProcKill() code for comments */
1070
1071 proc = MyProc;
1072 MyProc = NULL;
1074 DisownLatch(&proc->procLatch);
1075
1077
1078 /* Mark auxiliary proc no longer in use */
1079 proc->pid = 0;
1082
1083 /* Update shared estimate of spins_per_delay */
1085
1087}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:223
#define Assert(condition)
Definition c.h:873
bool ConditionVariableCancelSleep(void)
#define PANIC
Definition elog.h:42
#define elog(elevel,...)
Definition elog.h:226
ProcNumber MyProcNumber
Definition globals.c:90
void DisownLatch(Latch *latch)
Definition latch.c:144
void LWLockReleaseAll(void)
Definition lwlock.c:1892
void SwitchBackToLocalLatch(void)
Definition miscinit.c:242
void * arg
static int32 DatumGetInt32(Datum X)
Definition postgres.h:212
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
int update_spins_per_delay(int shared_spins_per_delay)
Definition s_lock.c:218
#define SpinLockRelease(lock)
Definition spin.h:61
#define SpinLockAcquire(lock)
Definition spin.h:59
PGPROC * MyProc
Definition proc.c:67
PROC_HDR * ProcGlobal
Definition proc.c:79
NON_EXEC_STATIC slock_t * ProcStructLock
Definition proc.c:76
LocalTransactionId lxid
Definition proc.h:218
ProcNumber procNumber
Definition proc.h:213
struct PGPROC::@131 vxid
Latch procLatch
Definition proc.h:187
int spins_per_delay
Definition proc.h:428
#define InvalidTransactionId
Definition transam.h:31
void pgstat_reset_wait_event_storage(void)
Definition wait_event.c:361

References arg, Assert, AuxiliaryProcs, ConditionVariableCancelSleep(), DatumGetInt32(), DisownLatch(), elog, fb(), INVALID_PROC_NUMBER, InvalidTransactionId, LWLockReleaseAll(), PGPROC::lxid, MyProc, MyProcNumber, NUM_AUXILIARY_PROCS, PANIC, PG_USED_FOR_ASSERTS_ONLY, pgstat_reset_wait_event_storage(), PGPROC::pid, ProcGlobal, PGPROC::procLatch, PGPROC::procNumber, ProcStructLock, SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, SwitchBackToLocalLatch(), update_spins_per_delay(), and PGPROC::vxid.

Referenced by InitAuxiliaryProcess().

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 2006 of file proc.c.

2007{
2009
2010 /* If we already did it, we don't need to do it again. */
2012 return;
2013
2014 /* We had better not be a follower. */
2016
2017 /* Create single-member group, containing only ourselves. */
2023}
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition ilist.h:347
#define LockHashPartitionLockByProc(leader_pgproc)
Definition lock.h:543
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ LW_EXCLUSIVE
Definition lwlock.h:112
dlist_head lockGroupMembers
Definition proc.h:322
dlist_node lockGroupLink
Definition proc.h:323
PGPROC * lockGroupLeader
Definition proc.h:321

References Assert, dlist_push_head(), fb(), 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 2036 of file proc.c.

2037{
2039 bool ok = false;
2040
2041 /* Group leader can't become member of group */
2042 Assert(MyProc != leader);
2043
2044 /* Can't already be a member of a group */
2046
2047 /* PID must be valid. */
2048 Assert(pid != 0);
2049
2050 /*
2051 * Get lock protecting the group fields. Note LockHashPartitionLockByProc
2052 * calculates the proc number based on the PGPROC slot without looking at
2053 * its contents, so we will acquire the correct lock even if the leader
2054 * PGPROC is in process of being recycled.
2055 */
2058
2059 /* Is this the leader we're looking for? */
2060 if (leader->pid == pid && leader->lockGroupLeader == leader)
2061 {
2062 /* OK, join the group */
2063 ok = true;
2064 MyProc->lockGroupLeader = leader;
2066 }
2068
2069 return ok;
2070}
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition ilist.h:364

References Assert, dlist_push_tail(), fb(), 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 1792 of file proc.c.

1793{
1794 int i;
1795
1796 /*
1797 * Acquire exclusive lock on the entire shared lock data structures. Must
1798 * grab LWLocks in partition-number order to avoid LWLock deadlock.
1799 *
1800 * Note that the deadlock check interrupt had better not be enabled
1801 * anywhere that this process itself holds lock partition locks, else this
1802 * will wait forever. Also note that LWLockAcquire creates a critical
1803 * section, so that this routine cannot be interrupted by cancel/die
1804 * interrupts.
1805 */
1806 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
1808
1809 /*
1810 * Check to see if we've been awoken by anyone in the interim.
1811 *
1812 * If we have, we can return and resume our transaction -- happy day.
1813 * Before we are awoken the process releasing the lock grants it to us so
1814 * we know that we don't have to wait anymore.
1815 *
1816 * We check by looking to see if we've been unlinked from the wait queue.
1817 * This is safe because we hold the lock partition lock.
1818 */
1819 if (MyProc->links.prev == NULL ||
1820 MyProc->links.next == NULL)
1821 goto check_done;
1822
1823#ifdef LOCK_DEBUG
1824 if (Debug_deadlocks)
1825 DumpAllLocks();
1826#endif
1827
1828 /* Run the deadlock check, and set deadlock_state for use by ProcSleep */
1830
1832 {
1833 /*
1834 * Oops. We have a deadlock.
1835 *
1836 * Get this process out of wait state. (Note: we could do this more
1837 * efficiently by relying on lockAwaited, but use this coding to
1838 * preserve the flexibility to kill some other transaction than the
1839 * one detecting the deadlock.)
1840 *
1841 * RemoveFromWaitQueue sets MyProc->waitStatus to
1842 * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
1843 * return from the signal handler.
1844 */
1847
1848 /*
1849 * We're done here. Transaction abort caused by the error that
1850 * ProcSleep will raise will cause any other locks we hold to be
1851 * released, thus allowing other processes to wake up; we don't need
1852 * to do that here. NOTE: an exception is that releasing locks we
1853 * hold doesn't consider the possibility of waiters that were blocked
1854 * behind us on the lock we just failed to get, and might now be
1855 * wakable because we're not in front of them anymore. However,
1856 * RemoveFromWaitQueue took care of waking up any such processes.
1857 */
1858 }
1859
1860 /*
1861 * And release locks. We do this in reverse order for two reasons: (1)
1862 * Anyone else who needs more than one of the locks will be trying to lock
1863 * them in increasing order; we don't want to release the other process
1864 * until it can get all the locks it needs. (2) This avoids O(N^2)
1865 * behavior inside LWLockRelease.
1866 */
1868 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
1870}
DeadLockState DeadLockCheck(PGPROC *proc)
Definition deadlock.c:220
int i
Definition isn.c:77
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition lock.c:2046
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:557
@ DS_HARD_DEADLOCK
Definition lock.h:515
#define LockHashPartitionLockByIndex(i)
Definition lock.h:531
#define NUM_LOCK_PARTITIONS
Definition lwlock.h:95
static DeadLockState deadlock_state
Definition proc.c:83
LOCKTAG tag
Definition lock.h:313
LOCK * waitLock
Definition proc.h:249
dlist_node links
Definition proc.h:181
dlist_node * next
Definition ilist.h:140
dlist_node * prev
Definition ilist.h:139

References Assert, deadlock_state, DeadLockCheck(), DS_HARD_DEADLOCK, fb(), 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 1878 of file proc.c.

1879{
1880 int save_errno = errno;
1881
1882 got_deadlock_timeout = true;
1883
1884 /*
1885 * Have to set the latch again, even if handle_sig_alarm already did. Back
1886 * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1887 * ever would be a problem, but setting a set latch again is cheap.
1888 *
1889 * Note that, when this function runs inside procsignal_sigusr1_handler(),
1890 * the handler function sets the latch again after the latch is set here.
1891 */
1893 errno = save_errno;
1894}
struct Latch * MyLatch
Definition globals.c:63
void SetLatch(Latch *latch)
Definition latch.c:290
static volatile sig_atomic_t got_deadlock_timeout
Definition proc.c:86

References fb(), got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres(), and ProcessRecoveryConflictInterrupt().

◆ FastPathLockShmemSize()

static Size FastPathLockShmemSize ( void  )
static

Definition at line 116 of file proc.c.

117{
118 Size size = 0;
123
124 /*
125 * Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are
126 * nicely aligned in each backend.
127 */
130
132
133 return size;
134}
#define MAXALIGN(LEN)
Definition c.h:826
uint64_t uint64
Definition c.h:547
size_t Size
Definition c.h:619
int MaxBackends
Definition globals.c:146
int FastPathLockGroupsPerBackend
Definition lock.c:202
unsigned int Oid
#define FastPathLockSlotsPerBackend()
Definition proc.h:94
Size add_size(Size s1, Size s2)
Definition shmem.c:482
Size mul_size(Size s1, Size s2)
Definition shmem.c:497
int max_prepared_xacts
Definition twophase.c:116

References add_size(), FastPathLockGroupsPerBackend, FastPathLockSlotsPerBackend, fb(), max_prepared_xacts, MAXALIGN, MaxBackends, mul_size(), and NUM_AUXILIARY_PROCS.

Referenced by InitProcGlobal(), and ProcGlobalShmemSize().

◆ GetLockHoldersAndWaiters()

void GetLockHoldersAndWaiters ( LOCALLOCK locallock,
StringInfo  lock_holders_sbuf,
StringInfo  lock_waiters_sbuf,
int lockHoldersNum 
)

Definition at line 1905 of file proc.c.

1907{
1910 LOCK *lock = locallock->lock;
1911 bool first_holder = true,
1912 first_waiter = true;
1913
1914#ifdef USE_ASSERT_CHECKING
1915 {
1916 uint32 hashcode = locallock->hashcode;
1918
1920 }
1921#endif
1922
1923 *lockHoldersNum = 0;
1924
1925 /*
1926 * Loop over the lock's procLocks to gather a list of all holders and
1927 * waiters. Thus we will be able to provide more detailed information for
1928 * lock debugging purposes.
1929 *
1930 * lock->procLocks contains all processes which hold or wait for this
1931 * lock.
1932 */
1934 {
1935 curproclock =
1936 dlist_container(PROCLOCK, lockLink, proc_iter.cur);
1937
1938 /*
1939 * We are a waiter if myProc->waitProcLock == curproclock; we are a
1940 * holder if it is NULL or something different.
1941 */
1942 if (curproclock->tag.myProc->waitProcLock == curproclock)
1943 {
1944 if (first_waiter)
1945 {
1947 curproclock->tag.myProc->pid);
1948 first_waiter = false;
1949 }
1950 else
1952 curproclock->tag.myProc->pid);
1953 }
1954 else
1955 {
1956 if (first_holder)
1957 {
1959 curproclock->tag.myProc->pid);
1960 first_holder = false;
1961 }
1962 else
1964 curproclock->tag.myProc->pid);
1965
1966 (*lockHoldersNum)++;
1967 }
1968 }
1969}
uint32_t uint32
Definition c.h:546
#define dlist_foreach(iter, lhead)
Definition ilist.h:623
#define dlist_container(type, membername, ptr)
Definition ilist.h:593
#define LockHashPartitionLock(hashcode)
Definition lock.h:528
bool LWLockHeldByMe(LWLock *lock)
Definition lwlock.c:1911
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
Definition lock.h:311
dlist_head procLocks
Definition lock.h:318

References appendStringInfo(), Assert, dlist_container, dlist_foreach, fb(), LockHashPartitionLock, LWLockHeldByMe(), and LOCK::procLocks.

Referenced by LockAcquireExtended(), and ProcSleep().

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 770 of file proc.c.

771{
772 /* use volatile pointer to prevent code rearrangement */
773 volatile PROC_HDR *procglobal = ProcGlobal;
774
776}
int startupBufferPinWaitBufId
Definition proc.h:430

References fb(), ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and ProcessRecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int nfree 
)

Definition at line 786 of file proc.c.

787{
788 dlist_iter iter;
789
790 Assert(n > 0);
791 Assert(nfree);
792
794
795 *nfree = 0;
797 {
798 (*nfree)++;
799 if (*nfree == n)
800 break;
801 }
802
804
805 return (*nfree == n);
806}
dlist_head freeProcs
Definition proc.h:408

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 619 of file proc.c.

620{
622 int proctype;
623
624 /*
625 * ProcGlobal should be set up already (if we are a backend, we inherit
626 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
627 */
628 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
629 elog(PANIC, "proc header uninitialized");
630
631 if (MyProc != NULL)
632 elog(ERROR, "you already exist");
633
636
637 /*
638 * We use the ProcStructLock to protect assignment and releasing of
639 * AuxiliaryProcs entries.
640 *
641 * While we are holding the ProcStructLock, also copy the current shared
642 * estimate of spins_per_delay to local storage.
643 */
645
647
648 /*
649 * Find a free auxproc ... *big* trouble if there isn't one ...
650 */
652 {
654 if (auxproc->pid == 0)
655 break;
656 }
658 {
660 elog(FATAL, "all AuxiliaryProcs are in use");
661 }
662
663 /* Mark auxiliary proc as in use by me */
664 /* use volatile pointer to prevent code rearrangement */
665 ((volatile PGPROC *) auxproc)->pid = MyProcPid;
666
668
669 MyProc = auxproc;
671
672 /*
673 * Initialize all fields of MyProc, except for those previously
674 * initialized by InitProcGlobal.
675 */
678 MyProc->fpVXIDLock = false;
689 MyProc->statusFlags = 0;
691 MyProc->lwWaitMode = 0;
695#ifdef USE_ASSERT_CHECKING
696 {
697 int i;
698
699 /* Last process should have released all locks. */
700 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
702 }
703#endif
704
705 /*
706 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
707 * on it. That allows us to repoint the process latch, which so far
708 * points to process local one, to the shared one.
709 */
712
713 /* now that we have a proc, report wait events to shared memory */
715
716 /* Check that group locking fields are in a proper initial state. */
719
720 /*
721 * We might be reusing a semaphore that belonged to a failed process. So
722 * be careful and reinitialize its value here. (This is not strictly
723 * necessary anymore, but seems like a good idea for cleanliness.)
724 */
726
727 /*
728 * Arrange to clean up at process exit.
729 */
731
732 /*
733 * Now that we have a PGPROC, we could try to acquire lightweight locks.
734 * Initialize local state needed for them. (Heavyweight locks cannot be
735 * acquired in aux processes.)
736 */
738
739#ifdef EXEC_BACKEND
740
741 /*
742 * Initialize backend-local pointers to all the shared data structures.
743 * (We couldn't do this until now because it needs LWLocks.)
744 */
747#endif
748}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:485
#define FATAL
Definition elog.h:41
#define ERROR
Definition elog.h:39
int MyProcPid
Definition globals.c:47
bool IsUnderPostmaster
Definition globals.c:120
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:372
void OwnLatch(Latch *latch)
Definition latch.c:126
#define InvalidLocalTransactionId
Definition lock.h:67
void InitLWLockAccess(void)
Definition lwlock.c:550
@ LW_WS_NOT_WAITING
Definition lwlock.h:30
void SwitchToSharedLatch(void)
Definition miscinit.c:215
BackendType MyBackendType
Definition miscinit.c:64
void RegisterPostmasterChildActive(void)
Definition pmsignal.c:290
void PGSemaphoreReset(PGSemaphore sema)
Definition posix_sema.c:290
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
#define InvalidOid
#define GetNumberFromPGProc(proc)
Definition proc.h:441
@ PROC_WAIT_STATUS_OK
Definition proc.h:142
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:1045
TransactionId xmin
Definition proc.h:195
PROCLOCK * waitProcLock
Definition proc.h:250
uint8 lwWaitMode
Definition proc.h:241
uint32 wait_event_info
Definition proc.h:296
BackendType backendType
Definition proc.h:231
uint8 statusFlags
Definition proc.h:259
Oid databaseId
Definition proc.h:225
pg_atomic_uint64 waitStart
Definition proc.h:254
bool fpVXIDLock
Definition proc.h:313
TransactionId xid
Definition proc.h:190
int delayChkptFlags
Definition proc.h:257
LocalTransactionId fpLocalTransactionId
Definition proc.h:314
PGSemaphore sem
Definition proc.h:184
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition proc.h:278
Oid roleId
Definition proc.h:226
ProcWaitStatus waitStatus
Definition proc.h:185
Oid tempNamespaceId
Definition proc.h:228
uint8 lwWaiting
Definition proc.h:240
void pgstat_set_wait_event_storage(uint32 *wait_event_info)
Definition wait_event.c:349

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

Referenced by AuxiliaryProcessMainCommon().

◆ InitProcess()

void InitProcess ( void  )

Definition at line 395 of file proc.c.

396{
397 dlist_head *procgloballist;
398
399 /*
400 * ProcGlobal should be set up already (if we are a backend, we inherit
401 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
402 */
403 if (ProcGlobal == NULL)
404 elog(PANIC, "proc header uninitialized");
405
406 if (MyProc != NULL)
407 elog(ERROR, "you already exist");
408
409 /*
410 * Before we start accessing the shared memory in a serious way, mark
411 * ourselves as an active postmaster child; this is so that the postmaster
412 * can detect it if we exit without cleaning up.
413 */
416
417 /*
418 * Decide which list should supply our PGPROC. This logic must match the
419 * way the freelists were constructed in InitProcGlobal().
420 */
422 procgloballist = &ProcGlobal->autovacFreeProcs;
423 else if (AmBackgroundWorkerProcess())
424 procgloballist = &ProcGlobal->bgworkerFreeProcs;
425 else if (AmWalSenderProcess())
426 procgloballist = &ProcGlobal->walsenderFreeProcs;
427 else
428 procgloballist = &ProcGlobal->freeProcs;
429
430 /*
431 * Try to get a proc struct from the appropriate free list. If this
432 * fails, we must be out of PGPROC structures (not to mention semaphores).
433 *
434 * While we are holding the ProcStructLock, also copy the current shared
435 * estimate of spins_per_delay to local storage.
436 */
438
440
441 if (!dlist_is_empty(procgloballist))
442 {
445 }
446 else
447 {
448 /*
449 * If we reach here, all the PGPROCs are in use. This is one of the
450 * possible places to detect "too many backends", so give the standard
451 * error message. XXX do we need to give a different failure message
452 * in the autovacuum case?
453 */
455 if (AmWalSenderProcess())
458 errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
462 errmsg("sorry, too many clients already")));
463 }
465
466 /*
467 * Cross-check that the PGPROC is of the type we expect; if this were not
468 * the case, it would get returned to the wrong list.
469 */
470 Assert(MyProc->procgloballist == procgloballist);
471
472 /*
473 * Initialize all fields of MyProc, except for those previously
474 * initialized by InitProcGlobal.
475 */
478 MyProc->fpVXIDLock = false;
485 /* databaseId and roleId will be filled in later */
491 MyProc->statusFlags = 0;
492 /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
496 MyProc->lwWaitMode = 0;
500#ifdef USE_ASSERT_CHECKING
501 {
502 int i;
503
504 /* Last process should have released all locks. */
505 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
507 }
508#endif
509
510 /* Initialize fields for sync rep */
514
515 /* Initialize fields for group XID clearing. */
519
520 /* Check that group locking fields are in a proper initial state. */
523
524 /* Initialize wait event information. */
526
527 /* Initialize fields for group transaction status update. */
528 MyProc->clogGroupMember = false;
534
535 /*
536 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
537 * on it. That allows us to repoint the process latch, which so far
538 * points to process local one, to the shared one.
539 */
542
543 /* now that we have a proc, report wait events to shared memory */
545
546 /*
547 * We might be reusing a semaphore that belonged to a failed process. So
548 * be careful and reinitialize its value here. (This is not strictly
549 * necessary anymore, but seems like a good idea for cleanliness.)
550 */
552
553 /*
554 * Arrange to clean up at backend exit.
555 */
557
558 /*
559 * Now that we have a PGPROC, we could try to acquire locks, so initialize
560 * local state needed for LWLocks, and the deadlock checker.
561 */
564
565#ifdef EXEC_BACKEND
566
567 /*
568 * Initialize backend-local pointers to all the shared data structures.
569 * (We couldn't do this until now because it needs LWLocks.)
570 */
573#endif
574}
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition atomics.h:237
#define TRANSACTION_STATUS_IN_PROGRESS
Definition clog.h:27
void InitDeadLockChecking(void)
Definition deadlock.c:144
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ereport(elevel,...)
Definition elog.h:150
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition ilist.h:450
#define AmAutoVacuumWorkerProcess()
Definition miscadmin.h:383
#define AmBackgroundWorkerProcess()
Definition miscadmin.h:384
#define AmWalSenderProcess()
Definition miscadmin.h:385
#define AmSpecialWorkerProcess()
Definition miscadmin.h:396
#define PROC_IS_AUTOVACUUM
Definition proc.h:58
static void ProcKill(int code, Datum arg)
Definition proc.c:923
bool procArrayGroupMember
Definition proc.h:286
XLogRecPtr clogGroupMemberLsn
Definition proc.h:306
pg_atomic_uint32 procArrayGroupNext
Definition proc.h:288
dlist_head * procgloballist
Definition proc.h:182
TransactionId clogGroupMemberXid
Definition proc.h:301
int64 clogGroupMemberPage
Definition proc.h:304
bool clogGroupMember
Definition proc.h:299
XLogRecPtr waitLSN
Definition proc.h:269
dlist_node syncRepLinks
Definition proc.h:271
int syncRepState
Definition proc.h:270
pg_atomic_uint32 clogGroupNext
Definition proc.h:300
XidStatus clogGroupMemberXidStatus
Definition proc.h:302
TransactionId procArrayGroupMemberXid
Definition proc.h:294
dlist_head autovacFreeProcs
Definition proc.h:410
dlist_head walsenderFreeProcs
Definition proc.h:414
dlist_head bgworkerFreeProcs
Definition proc.h:412
#define SYNC_REP_NOT_WAITING
Definition syncrep.h:30
int max_wal_senders
Definition walsender.c:129
#define InvalidXLogRecPtr
Definition xlogdefs.h:28
static struct link * links
Definition zic.c:302

References AmAutoVacuumWorkerProcess, AmBackgroundWorkerProcess, AmSpecialWorkerProcess, AmWalSenderProcess, Assert, PROC_HDR::autovacFreeProcs, PGPROC::backendType, PROC_HDR::bgworkerFreeProcs, PGPROC::clogGroupMember, PGPROC::clogGroupMemberLsn, PGPROC::clogGroupMemberPage, PGPROC::clogGroupMemberXid, PGPROC::clogGroupMemberXidStatus, PGPROC::clogGroupNext, PGPROC::databaseId, PGPROC::delayChkptFlags, dlist_container, dlist_is_empty(), dlist_node_init(), dlist_pop_head_node(), elog, ereport, errcode(), errmsg(), ERROR, FATAL, fb(), PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, PROC_HDR::freeProcs, GetNumberFromPGProc, i, InitDeadLockChecking(), InitLWLockAccess(), INVALID_PROC_NUMBER, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsUnderPostmaster, PGPROC::links, links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LW_WS_NOT_WAITING, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, max_wal_senders, MyBackendType, MyProc, PGPROC::myProcLocks, MyProcNumber, 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, PGPROC::procNumber, ProcStructLock, RegisterPostmasterChildActive(), 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::vxid, 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(), BackendMain(), BackgroundWorkerMain(), BootstrapModeMain(), PostgresSingleUserMain(), and ReplSlotSyncWorkerMain().

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 584 of file proc.c.

585{
586 Assert(MyProc != NULL);
587
588 /*
589 * Add our PGPROC to the PGPROC array in shared memory.
590 */
592
593 /*
594 * Arrange to clean that up at backend exit.
595 */
597}
void ProcArrayAdd(PGPROC *proc)
Definition procarray.c:470
static void RemoveProcFromArray(int code, Datum arg)
Definition proc.c:912

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 194 of file proc.c.

195{
196 PGPROC *procs;
197 int i,
198 j;
199 bool found;
201
202 /* Used for setup of per-backend fast-path slots. */
203 char *fpPtr,
208 char *ptr;
209
210 /* Create the ProcGlobal shared structure */
211 ProcGlobal = (PROC_HDR *)
212 ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
213 Assert(!found);
214
215 /*
216 * Initialize the data structures.
217 */
228
229 /*
230 * Create and initialize all the PGPROC structures we'll need. There are
231 * six separate consumers: (1) normal backends, (2) autovacuum workers and
232 * special workers, (3) background workers, (4) walsenders, (5) auxiliary
233 * processes, and (6) prepared transactions. (For largely-historical
234 * reasons, we combine autovacuum and special workers into one category
235 * with a single freelist.) Each PGPROC structure is dedicated to exactly
236 * one of these purposes, and they do not move between groups.
237 */
239
240 ptr = ShmemInitStruct("PGPROC structures",
242 &found);
243
244 MemSet(ptr, 0, requestSize);
245
246 procs = (PGPROC *) ptr;
247 ptr = ptr + TotalProcs * sizeof(PGPROC);
248
249 ProcGlobal->allProcs = procs;
250 /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
252
253 /*
254 * Allocate arrays mirroring PGPROC fields in a dense manner. See
255 * PROC_HDR.
256 *
257 * XXX: It might make sense to increase padding for these arrays, given
258 * how hotly they are accessed.
259 */
260 ProcGlobal->xids = (TransactionId *) ptr;
261 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
262
264 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
265
266 ProcGlobal->statusFlags = (uint8 *) ptr;
267 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
268
269 /* make sure wer didn't overflow */
270 Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
271
272 /*
273 * Allocate arrays for fast-path locks. Those are variable-length, so
274 * can't be included in PGPROC directly. We allocate a separate piece of
275 * shared memory and then divide that between backends.
276 */
279
281
282 fpPtr = ShmemInitStruct("Fast-Path Lock Array",
284 &found);
285
287
288 /* For asserts checking we did not overflow. */
290
291 /* Reserve space for semaphores. */
293
294 for (i = 0; i < TotalProcs; i++)
295 {
296 PGPROC *proc = &procs[i];
297
298 /* Common initialization for all PGPROCs, regardless of type. */
299
300 /*
301 * Set the fast-path lock arrays, and move the pointer. We interleave
302 * the two arrays, to (hopefully) get some locality for each backend.
303 */
304 proc->fpLockBits = (uint64 *) fpPtr;
306
307 proc->fpRelId = (Oid *) fpPtr;
309
311
312 /*
313 * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
314 * dummy PGPROCs don't need these though - they're never associated
315 * with a real process
316 */
318 {
319 proc->sem = PGSemaphoreCreate();
320 InitSharedLatch(&(proc->procLatch));
322 }
323
324 /*
325 * Newly created PGPROCs for normal backends, autovacuum workers,
326 * special workers, bgworkers, and walsenders must be queued up on the
327 * appropriate free list. Because there can only ever be a small,
328 * fixed number of auxiliary processes, no free list is used in that
329 * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs
330 * for prepared transactions are added to a free list by
331 * TwoPhaseShmemInit().
332 */
333 if (i < MaxConnections)
334 {
335 /* PGPROC for normal backend, add to freeProcs list */
338 }
340 {
341 /* PGPROC for AV or special worker, add to autovacFreeProcs list */
344 }
346 {
347 /* PGPROC for bgworker, add to bgworkerFreeProcs list */
350 }
351 else if (i < MaxBackends)
352 {
353 /* PGPROC for walsender, add to walsenderFreeProcs list */
356 }
357
358 /* Initialize myProcLocks[] shared memory queues. */
359 for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
360 dlist_init(&(proc->myProcLocks[j]));
361
362 /* Initialize lockGroupMembers list. */
364
365 /*
366 * Initialize the atomic variables, otherwise, it won't be safe to
367 * access them for backends that aren't currently in use.
368 */
371 pg_atomic_init_u64(&(proc->waitStart), 0);
372 }
373
374 /* Should have consumed exactly the expected amount of fast-path memory. */
376
377 /*
378 * Save pointers to the blocks of PGPROC structures reserved for auxiliary
379 * processes and prepared transactions.
380 */
381 AuxiliaryProcs = &procs[MaxBackends];
383
384 /* Create ProcStructLock spinlock, too */
385 ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock",
386 sizeof(slock_t),
387 &found);
389}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:219
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:453
int autovacuum_worker_slots
Definition autovacuum.c:118
uint8_t uint8
Definition c.h:544
#define MemSet(start, val, len)
Definition c.h:1013
uint32 TransactionId
Definition c.h:666
int MaxConnections
Definition globals.c:143
int max_worker_processes
Definition globals.c:144
static void dlist_init(dlist_head *head)
Definition ilist.h:314
int j
Definition isn.c:78
void InitSharedLatch(Latch *latch)
Definition latch.c:93
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition lwlock.c:698
void PGReserveSemaphores(int maxSemas)
Definition posix_sema.c:196
PGSemaphore PGSemaphoreCreate(void)
Definition posix_sema.c:257
#define NUM_SPECIAL_WORKER_PROCS
Definition proc.h:450
#define DEFAULT_SPINS_PER_DELAY
Definition s_lock.h:726
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
#define SpinLockInit(lock)
Definition spin.h:57
PGPROC * PreparedXactProcs
Definition proc.c:81
static Size PGProcShmemSize(void)
Definition proc.c:98
static Size FastPathLockShmemSize(void)
Definition proc.c:116
int ProcGlobalSemas(void)
Definition proc.c:159
LWLock fpInfoLock
Definition proc.h:310
Oid * fpRelId
Definition proc.h:312
uint64 * fpLockBits
Definition proc.h:311
uint8 * statusFlags
Definition proc.h:403
XidCacheStatus * subxidStates
Definition proc.h:397
ProcNumber checkpointerProc
Definition proc.h:425
PGPROC * allProcs
Definition proc.h:388
pg_atomic_uint32 clogGroupFirst
Definition proc.h:418
TransactionId * xids
Definition proc.h:391
ProcNumber walwriterProc
Definition proc.h:424
pg_atomic_uint32 procArrayGroupFirst
Definition proc.h:416
uint32 allProcCount
Definition proc.h:406

References PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert, PROC_HDR::autovacFreeProcs, autovacuum_worker_slots, AuxiliaryProcs, PROC_HDR::bgworkerFreeProcs, PROC_HDR::checkpointerProc, PROC_HDR::clogGroupFirst, PGPROC::clogGroupNext, DEFAULT_SPINS_PER_DELAY, dlist_init(), dlist_push_tail(), FastPathLockGroupsPerBackend, FastPathLockShmemSize(), FastPathLockSlotsPerBackend, fb(), PGPROC::fpInfoLock, PGPROC::fpLockBits, PGPROC::fpRelId, PROC_HDR::freeProcs, i, InitSharedLatch(), INVALID_PROC_NUMBER, j, PGPROC::links, PGPROC::lockGroupMembers, LWLockInitialize(), max_prepared_xacts, max_worker_processes, MAXALIGN, MaxBackends, MaxConnections, MemSet, PGPROC::myProcLocks, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, NUM_SPECIAL_WORKER_PROCS, pg_atomic_init_u32(), pg_atomic_init_u64(), PG_USED_FOR_ASSERTS_ONLY, PGProcShmemSize(), PGReserveSemaphores(), PGSemaphoreCreate(), PreparedXactProcs, PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::procgloballist, ProcGlobalSemas(), PGPROC::procLatch, ProcStructLock, PGPROC::sem, ShmemInitStruct(), SpinLockInit, PROC_HDR::spins_per_delay, PROC_HDR::startupBufferPinWaitBufId, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PGPROC::waitStart, PROC_HDR::walsenderFreeProcs, PROC_HDR::walwriterProc, and PROC_HDR::xids.

Referenced by CreateOrAttachShmemStructs().

◆ JoinWaitQueue()

ProcWaitStatus JoinWaitQueue ( LOCALLOCK locallock,
LockMethod  lockMethodTable,
bool  dontWait 
)

Definition at line 1145 of file proc.c.

1146{
1147 LOCKMODE lockmode = locallock->tag.mode;
1148 LOCK *lock = locallock->lock;
1149 PROCLOCK *proclock = locallock->proclock;
1150 uint32 hashcode = locallock->hashcode;
1156 bool early_deadlock = false;
1157 PGPROC *leader = MyProc->lockGroupLeader;
1158
1160
1161 /*
1162 * Set bitmask of locks this process already holds on this object.
1163 */
1164 myHeldLocks = MyProc->heldLocks = proclock->holdMask;
1165
1166 /*
1167 * Determine which locks we're already holding.
1168 *
1169 * If group locking is in use, locks held by members of my locking group
1170 * need to be included in myHeldLocks. This is not required for relation
1171 * extension lock which conflict among group members. However, including
1172 * them in myHeldLocks will give group members the priority to get those
1173 * locks as compared to other backends which are also trying to acquire
1174 * those locks. OTOH, we can avoid giving priority to group members for
1175 * that kind of locks, but there doesn't appear to be a clear advantage of
1176 * the same.
1177 */
1178 myProcHeldLocks = proclock->holdMask;
1180 if (leader != NULL)
1181 {
1182 dlist_iter iter;
1183
1184 dlist_foreach(iter, &lock->procLocks)
1185 {
1187
1188 otherproclock = dlist_container(PROCLOCK, lockLink, iter.cur);
1189
1190 if (otherproclock->groupLeader == leader)
1191 myHeldLocks |= otherproclock->holdMask;
1192 }
1193 }
1194
1195 /*
1196 * Determine where to add myself in the wait queue.
1197 *
1198 * Normally I should go at the end of the queue. However, if I already
1199 * hold locks that conflict with the request of any previous waiter, put
1200 * myself in the queue just in front of the first such waiter. This is not
1201 * a necessary step, since deadlock detection would move me to before that
1202 * waiter anyway; but it's relatively cheap to detect such a conflict
1203 * immediately, and avoid delaying till deadlock timeout.
1204 *
1205 * Special case: if I find I should go in front of some waiter, check to
1206 * see if I conflict with already-held locks or the requests before that
1207 * waiter. If not, then just grant myself the requested lock immediately.
1208 * This is the same as the test for immediate grant in LockAcquire, except
1209 * we are only considering the part of the wait queue before my insertion
1210 * point.
1211 */
1213 {
1215 dlist_iter iter;
1216
1218 {
1219 PGPROC *proc = dlist_container(PGPROC, links, iter.cur);
1220
1221 /*
1222 * If we're part of the same locking group as this waiter, its
1223 * locks neither conflict with ours nor contribute to
1224 * aheadRequests.
1225 */
1226 if (leader != NULL && leader == proc->lockGroupLeader)
1227 continue;
1228
1229 /* Must he wait for me? */
1230 if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
1231 {
1232 /* Must I wait for him ? */
1233 if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
1234 {
1235 /*
1236 * Yes, so we have a deadlock. Easiest way to clean up
1237 * correctly is to call RemoveFromWaitQueue(), but we
1238 * can't do that until we are *on* the wait queue. So, set
1239 * a flag to check below, and break out of loop. Also,
1240 * record deadlock info for later message.
1241 */
1242 RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
1243 early_deadlock = true;
1244 break;
1245 }
1246 /* I must go before this waiter. Check special case. */
1247 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1248 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1249 proclock))
1250 {
1251 /* Skip the wait and just grant myself the lock. */
1252 GrantLock(lock, proclock, lockmode);
1253 return PROC_WAIT_STATUS_OK;
1254 }
1255
1256 /* Put myself into wait queue before conflicting process */
1257 insert_before = proc;
1258 break;
1259 }
1260 /* Nope, so advance to next waiter */
1262 }
1263 }
1264
1265 /*
1266 * If we detected deadlock, give up without waiting. This must agree with
1267 * CheckDeadLock's recovery code.
1268 */
1269 if (early_deadlock)
1271
1272 /*
1273 * At this point we know that we'd really need to sleep. If we've been
1274 * commanded not to do that, bail out.
1275 */
1276 if (dontWait)
1278
1279 /*
1280 * Insert self into queue, at the position determined above.
1281 */
1282 if (insert_before)
1284 else
1286
1287 lock->waitMask |= LOCKBIT_ON(lockmode);
1288
1289 /* Set up wait information in PGPROC object, too */
1291 MyProc->waitLock = lock;
1292 MyProc->waitProcLock = proclock;
1293 MyProc->waitLockMode = lockmode;
1294
1296
1298}
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition deadlock.c:1147
static void dclist_push_tail(dclist_head *head, dlist_node *node)
Definition ilist.h:709
static bool dclist_is_empty(const dclist_head *head)
Definition ilist.h:682
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 GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1658
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition lock.c:1529
#define LOCKBIT_ON(lockmode)
Definition lock.h:86
int LOCKMODE
Definition lockdefs.h:26
int LOCKMASK
Definition lockdefs.h:25
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1955
@ PROC_WAIT_STATUS_WAITING
Definition proc.h:143
@ PROC_WAIT_STATUS_ERROR
Definition proc.h:144
dclist_head waitProcs
Definition lock.h:319
LOCKMASK waitMask
Definition lock.h:317
LOCKMODE waitLockMode
Definition proc.h:251
LOCKMASK heldLocks
Definition proc.h:252
LOCKMASK holdMask
Definition lock.h:378
dlist_node * cur
Definition ilist.h:179

References Assert, dlist_iter::cur, dclist_foreach, dclist_insert_before(), dclist_is_empty(), dclist_push_tail(), dlist_container, dlist_foreach, fb(), GrantLock(), PGPROC::heldLocks, PROCLOCK::holdMask, PGPROC::links, links, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, LW_EXCLUSIVE, LWLockHeldByMeInMode(), MyProc, PG_USED_FOR_ASSERTS_ONLY, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_OK, PROC_WAIT_STATUS_WAITING, LOCK::procLocks, RememberSimpleDeadLock(), PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, and PGPROC::waitStatus.

Referenced by LockAcquireExtended().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 817 of file proc.c.

818{
822
824
826
827 /* Nothing to do if we weren't waiting for a lock */
829 if (lockAwaited == NULL)
830 {
832 return;
833 }
834
835 /*
836 * Turn off the deadlock and lock timeout timers, if they are still
837 * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
838 * indicator flag, since this function is executed before
839 * ProcessInterrupts when responding to SIGINT; else we'd lose the
840 * knowledge that the SIGINT came from a lock timeout and not an external
841 * source.
842 */
844 timeouts[0].keep_indicator = false;
845 timeouts[1].id = LOCK_TIMEOUT;
846 timeouts[1].keep_indicator = true;
848
849 /* Unlink myself from the wait queue, if on it (might not be anymore!) */
852
854 {
855 /* We could not have been granted the lock yet */
857 }
858 else
859 {
860 /*
861 * Somebody kicked us off the lock queue already. Perhaps they
862 * granted us the lock, or perhaps they detected a deadlock. If they
863 * did grant us the lock, we'd better remember it in our local lock
864 * table.
865 */
868 }
869
871
873
875}
static bool dlist_node_is_detached(const dlist_node *node)
Definition ilist.h:525
void GrantAwaitedLock(void)
Definition lock.c:1889
void ResetAwaitedLock(void)
Definition lock.c:1907
void AbortStrongLockAcquire(void)
Definition lock.c:1860
LOCALLOCK * GetAwaitedLock(void)
Definition lock.c:1898
#define RESUME_INTERRUPTS()
Definition miscadmin.h:136
#define HOLD_INTERRUPTS()
Definition miscadmin.h:134
void disable_timeouts(const DisableTimeoutParams *timeouts, int count)
Definition timeout.c:718
@ LOCK_TIMEOUT
Definition timeout.h:28
@ DEADLOCK_TIMEOUT
Definition timeout.h:27

References AbortStrongLockAcquire(), DEADLOCK_TIMEOUT, disable_timeouts(), dlist_node_is_detached(), fb(), GetAwaitedLock(), GrantAwaitedLock(), HOLD_INTERRUPTS, PGPROC::links, LOCK_TIMEOUT, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), ResetAwaitedLock(), RESUME_INTERRUPTS, and PGPROC::waitStatus.

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

◆ PGProcShmemSize()

static Size PGProcShmemSize ( void  )
static

Definition at line 98 of file proc.c.

99{
100 Size size = 0;
103
104 size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
105 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
106 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
107 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
108
109 return size;
110}

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

Referenced by InitProcGlobal(), and ProcGlobalShmemSize().

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 159 of file proc.c.

160{
161 /*
162 * We need a sema per backend (including autovacuum), plus one for each
163 * auxiliary process.
164 */
166}

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by InitializeShmemGUCs(), InitProcGlobal(), and ProcGlobalShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 140 of file proc.c.

141{
142 Size size = 0;
143
144 /* ProcGlobal */
145 size = add_size(size, sizeof(PROC_HDR));
146 size = add_size(size, sizeof(slock_t));
147
149 size = add_size(size, PGProcShmemSize());
150 size = add_size(size, FastPathLockShmemSize());
151
152 return size;
153}
Size PGSemaphoreShmemSize(int maxSemas)
Definition posix_sema.c:165

References add_size(), FastPathLockShmemSize(), fb(), PGProcShmemSize(), PGSemaphoreShmemSize(), and ProcGlobalSemas().

Referenced by CalculateShmemSize().

◆ ProcKill()

static void ProcKill ( int  code,
Datum  arg 
)
static

Definition at line 923 of file proc.c.

924{
925 PGPROC *proc;
926 dlist_head *procgloballist;
927
928 Assert(MyProc != NULL);
929
930 /* not safe if forked by system(), etc. */
931 if (MyProc->pid != (int) getpid())
932 elog(PANIC, "ProcKill() called in child process");
933
934 /* Make sure we're out of the sync rep lists */
936
937#ifdef USE_ASSERT_CHECKING
938 {
939 int i;
940
941 /* Last process should have released all locks. */
942 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
944 }
945#endif
946
947 /*
948 * Release any LW locks I am holding. There really shouldn't be any, but
949 * it's cheap to check again before we cut the knees off the LWLock
950 * facility by releasing our PGPROC ...
951 */
953
954 /*
955 * Cleanup waiting for LSN if any.
956 */
958
959 /* Cancel any pending condition variable sleep, too */
961
962 /*
963 * Detach from any lock group of which we are a member. If the leader
964 * exits before all other group members, its PGPROC will remain allocated
965 * until the last group process exits; that process must return the
966 * leader's PGPROC to the appropriate list.
967 */
969 {
970 PGPROC *leader = MyProc->lockGroupLeader;
972
976 if (dlist_is_empty(&leader->lockGroupMembers))
977 {
978 leader->lockGroupLeader = NULL;
979 if (leader != MyProc)
980 {
981 procgloballist = leader->procgloballist;
982
983 /* Leader exited first; return its PGPROC. */
985 dlist_push_head(procgloballist, &leader->links);
987 }
988 }
989 else if (leader != MyProc)
992 }
993
994 /*
995 * Reset MyLatch to the process local one. This is so that signal
996 * handlers et al can continue using the latch after the shared latch
997 * isn't ours anymore.
998 *
999 * Similarly, stop reporting wait events to MyProc->wait_event_info.
1000 *
1001 * After that clear MyProc and disown the shared latch.
1002 */
1005
1006 proc = MyProc;
1007 MyProc = NULL;
1009 DisownLatch(&proc->procLatch);
1010
1011 /* Mark the proc no longer in use */
1012 proc->pid = 0;
1015
1016 procgloballist = proc->procgloballist;
1018
1019 /*
1020 * If we're still a member of a locking group, that means we're a leader
1021 * which has somehow exited before its children. The last remaining child
1022 * will release our PGPROC. Otherwise, release it now.
1023 */
1024 if (proc->lockGroupLeader == NULL)
1025 {
1026 /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
1028
1029 /* Return PGPROC structure (and semaphore) to appropriate freelist */
1030 dlist_push_tail(procgloballist, &proc->links);
1031 }
1032
1033 /* Update shared estimate of spins_per_delay */
1035
1037}
static void dlist_delete(dlist_node *node)
Definition ilist.h:405
void SyncRepCleanupAtProcExit(void)
Definition syncrep.c:416
void WaitLSNCleanup(void)
Definition xlogwait.c:338

References Assert, ConditionVariableCancelSleep(), DisownLatch(), dlist_delete(), dlist_is_empty(), dlist_push_head(), dlist_push_tail(), elog, fb(), i, INVALID_PROC_NUMBER, InvalidTransactionId, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupLink, PGPROC::lockGroupMembers, LockHashPartitionLockByProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LWLockReleaseAll(), PGPROC::lxid, MyProc, PGPROC::myProcLocks, MyProcNumber, NUM_LOCK_PARTITIONS, PANIC, pgstat_reset_wait_event_storage(), PGPROC::pid, ProcGlobal, PGPROC::procgloballist, PGPROC::procLatch, PGPROC::procNumber, ProcStructLock, SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, SwitchBackToLocalLatch(), SyncRepCleanupAtProcExit(), update_spins_per_delay(), PGPROC::vxid, and WaitLSNCleanup().

Referenced by InitProcess().

◆ ProcLockWakeup()

void ProcLockWakeup ( LockMethod  lockMethodTable,
LOCK lock 
)

Definition at line 1744 of file proc.c.

1745{
1749
1751 return;
1752
1754 {
1755 PGPROC *proc = dlist_container(PGPROC, links, miter.cur);
1756 LOCKMODE lockmode = proc->waitLockMode;
1757
1758 /*
1759 * Waken if (a) doesn't conflict with requests of earlier waiters, and
1760 * (b) doesn't conflict with already-held locks.
1761 */
1762 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1763 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1764 proc->waitProcLock))
1765 {
1766 /* OK to waken */
1767 GrantLock(lock, proc->waitProcLock, lockmode);
1768 /* removes proc from the lock's waiting process queue */
1770 }
1771 else
1772 {
1773 /*
1774 * Lock conflicts: Don't wake, but remember requested mode for
1775 * later checks.
1776 */
1777 aheadRequests |= LOCKBIT_ON(lockmode);
1778 }
1779 }
1780}
#define dclist_foreach_modify(iter, lhead)
Definition ilist.h:973
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition proc.c:1716

References dclist_foreach_modify, dclist_is_empty(), dlist_container, fb(), 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 895 of file proc.c.

896{
897 if (!MyProc)
898 return;
899 /* If waiting, get off wait queue (should only be needed after error) */
901 /* Release standard locks, including session-level if aborting */
903 /* Release transaction-level advisory locks */
905}
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition lock.c:2307
#define DEFAULT_LOCKMETHOD
Definition lock.h:127
#define USER_LOCKMETHOD
Definition lock.h:128
void LockErrorCleanup(void)
Definition proc.c:817

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 1991 of file proc.c.

1992{
1994 elog(ERROR, "procNumber out of range");
1995
1996 SetLatch(&GetPGProcByNumber(procNumber)->procLatch);
1997}
#define GetPGProcByNumber(n)
Definition proc.h:440

References PROC_HDR::allProcCount, elog, ERROR, fb(), GetPGProcByNumber, ProcGlobal, and SetLatch().

Referenced by ReleasePredicateLocks(), and WakePinCountWaiter().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock)

Definition at line 1314 of file proc.c.

1315{
1316 LOCKMODE lockmode = locallock->tag.mode;
1317 LOCK *lock = locallock->lock;
1318 uint32 hashcode = locallock->hashcode;
1321 bool allow_autovacuum_cancel = true;
1322 bool logged_recovery_conflict = false;
1324
1325 /* The caller must've armed the on-error cleanup mechanism */
1328
1329 /*
1330 * Now that we will successfully clean up after an ereport, it's safe to
1331 * check to see if there's a buffer pin deadlock against the Startup
1332 * process. Of course, that's only necessary if we're doing Hot Standby
1333 * and are not the Startup process ourselves.
1334 */
1337
1338 /* Reset deadlock_state before enabling the timeout handler */
1340 got_deadlock_timeout = false;
1341
1342 /*
1343 * Set timer so we can wake up after awhile and check for a deadlock. If a
1344 * deadlock is detected, the handler sets MyProc->waitStatus =
1345 * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
1346 * rather than success.
1347 *
1348 * By delaying the check until we've waited for a bit, we can avoid
1349 * running the rather expensive deadlock-check code in most cases.
1350 *
1351 * If LockTimeout is set, also enable the timeout for that. We can save a
1352 * few cycles by enabling both timeout sources in one call.
1353 *
1354 * If InHotStandby we set lock waits slightly later for clarity with other
1355 * code.
1356 */
1357 if (!InHotStandby)
1358 {
1359 if (LockTimeout > 0)
1360 {
1362
1364 timeouts[0].type = TMPARAM_AFTER;
1365 timeouts[0].delay_ms = DeadlockTimeout;
1366 timeouts[1].id = LOCK_TIMEOUT;
1367 timeouts[1].type = TMPARAM_AFTER;
1368 timeouts[1].delay_ms = LockTimeout;
1370 }
1371 else
1373
1374 /*
1375 * Use the current time obtained for the deadlock timeout timer as
1376 * waitStart (i.e., the time when this process started waiting for the
1377 * lock). Since getting the current time newly can cause overhead, we
1378 * reuse the already-obtained time to avoid that overhead.
1379 *
1380 * Note that waitStart is updated without holding the lock table's
1381 * partition lock, to avoid the overhead by additional lock
1382 * acquisition. This can cause "waitstart" in pg_locks to become NULL
1383 * for a very short period of time after the wait started even though
1384 * "granted" is false. This is OK in practice because we can assume
1385 * that users are likely to look at "waitstart" when waiting for the
1386 * lock for a long time.
1387 */
1390 }
1392 {
1393 /*
1394 * Set the wait start timestamp if logging is enabled and in hot
1395 * standby.
1396 */
1398 }
1399
1400 /*
1401 * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1402 * will not wait. But a set latch does not necessarily mean that the lock
1403 * is free now, as there are many other sources for latch sets than
1404 * somebody releasing the lock.
1405 *
1406 * We process interrupts whenever the latch has been set, so cancel/die
1407 * interrupts are processed quickly. This means we must not mind losing
1408 * control to a cancel/die interrupt here. We don't, because we have no
1409 * shared-state-change work to do after being granted the lock (the
1410 * grantor did it all). We do have to worry about canceling the deadlock
1411 * timeout and updating the locallock table, but if we lose control to an
1412 * error, LockErrorCleanup will fix that up.
1413 */
1414 do
1415 {
1416 if (InHotStandby)
1417 {
1418 bool maybe_log_conflict =
1420
1421 /* Set a timer and wait for that or for the lock to be granted */
1424
1425 /*
1426 * Emit the log message if the startup process is waiting longer
1427 * than deadlock_timeout for recovery conflict on lock.
1428 */
1430 {
1432
1435 {
1437 int cnt;
1438
1439 vxids = GetLockConflicts(&locallock->tag.lock,
1440 AccessExclusiveLock, &cnt);
1441
1442 /*
1443 * Log the recovery conflict and the list of PIDs of
1444 * backends holding the conflicting lock. Note that we do
1445 * logging even if there are no such backends right now
1446 * because the startup process here has already waited
1447 * longer than deadlock_timeout.
1448 */
1451 cnt > 0 ? vxids : NULL, true);
1453 }
1454 }
1455 }
1456 else
1457 {
1459 PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1461 /* check for deadlocks first, as that's probably log-worthy */
1463 {
1464 CheckDeadLock();
1465 got_deadlock_timeout = false;
1466 }
1468 }
1469
1470 /*
1471 * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
1472 * else asynchronously. Read it just once per loop to prevent
1473 * surprising behavior (such as missing log messages).
1474 */
1475 myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
1476
1477 /*
1478 * If we are not deadlocked, but are waiting on an autovacuum-induced
1479 * task, send a signal to interrupt it.
1480 */
1482 {
1484 uint8 statusFlags;
1487
1488 /*
1489 * Grab info we need, then release lock immediately. Note this
1490 * coding means that there is a tiny chance that the process
1491 * terminates its current transaction and starts a different one
1492 * before we have a change to send the signal; the worst possible
1493 * consequence is that a for-wraparound vacuum is canceled. But
1494 * that could happen in any case unless we were to do kill() with
1495 * the lock held, which is much more undesirable.
1496 */
1498 statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1500 locktag_copy = lock->tag;
1502
1503 /*
1504 * Only do it if the worker is not working to protect against Xid
1505 * wraparound.
1506 */
1507 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
1508 !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
1509 {
1510 int pid = autovac->pid;
1511
1512 /* report the case, if configured to do so */
1514 {
1516 StringInfoData logbuf; /* errdetail for server log */
1517
1522 "Process %d waits for %s on %s.",
1523 MyProcPid,
1525 locktagbuf.data);
1526
1528 (errmsg_internal("sending cancel to blocking autovacuum PID %d",
1529 pid),
1530 errdetail_log("%s", logbuf.data)));
1531
1532 pfree(locktagbuf.data);
1533 pfree(logbuf.data);
1534 }
1535
1536 /* send the autovacuum worker Back to Old Kent Road */
1537 if (kill(pid, SIGINT) < 0)
1538 {
1539 /*
1540 * There's a race condition here: once we release the
1541 * ProcArrayLock, it's possible for the autovac worker to
1542 * close up shop and exit before we can do the kill().
1543 * Therefore, we do not whinge about no-such-process.
1544 * Other errors such as EPERM could conceivably happen if
1545 * the kernel recycles the PID fast enough, but such cases
1546 * seem improbable enough that it's probably best to issue
1547 * a warning if we see some other errno.
1548 */
1549 if (errno != ESRCH)
1551 (errmsg("could not send signal to process %d: %m",
1552 pid)));
1553 }
1554 }
1555
1556 /* prevent signal from being sent again more than once */
1558 }
1559
1560 /*
1561 * If awoken after the deadlock check interrupt has run, and
1562 * log_lock_waits is on, then report about the wait.
1563 */
1565 {
1569 const char *modename;
1570 long secs;
1571 int usecs;
1572 long msecs;
1573 int lockHoldersNum = 0;
1574
1578
1579 DescribeLockTag(&buf, &locallock->tag.lock);
1580 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1581 lockmode);
1584 &secs, &usecs);
1585 msecs = secs * 1000 + usecs / 1000;
1586 usecs = usecs % 1000;
1587
1588 /* Gather a list of all lock holders and waiters */
1593
1595 ereport(LOG,
1596 (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1597 MyProcPid, modename, buf.data, msecs, usecs),
1598 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1599 "Processes holding the lock: %s. Wait queue: %s.",
1601 else if (deadlock_state == DS_HARD_DEADLOCK)
1602 {
1603 /*
1604 * This message is a bit redundant with the error that will be
1605 * reported subsequently, but in some cases the error report
1606 * might not make it to the log (eg, if it's caught by an
1607 * exception handler), and we want to ensure all long-wait
1608 * events get logged.
1609 */
1610 ereport(LOG,
1611 (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1612 MyProcPid, modename, buf.data, msecs, usecs),
1613 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1614 "Processes holding the lock: %s. Wait queue: %s.",
1616 }
1617
1619 ereport(LOG,
1620 (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1621 MyProcPid, modename, buf.data, msecs, usecs),
1622 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1623 "Processes holding the lock: %s. Wait queue: %s.",
1626 ereport(LOG,
1627 (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1628 MyProcPid, modename, buf.data, msecs, usecs)));
1629 else
1630 {
1632
1633 /*
1634 * Currently, the deadlock checker always kicks its own
1635 * process, which means that we'll only see
1636 * PROC_WAIT_STATUS_ERROR when deadlock_state ==
1637 * DS_HARD_DEADLOCK, and there's no need to print redundant
1638 * messages. But for completeness and future-proofing, print
1639 * a message if it looks like someone else kicked us off the
1640 * lock.
1641 */
1643 ereport(LOG,
1644 (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1645 MyProcPid, modename, buf.data, msecs, usecs),
1646 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1647 "Processes holding the lock: %s. Wait queue: %s.",
1649 }
1650
1651 /*
1652 * At this point we might still need to wait for the lock. Reset
1653 * state so we don't print the above messages again.
1654 */
1656
1657 pfree(buf.data);
1660 }
1662
1663 /*
1664 * Disable the timers, if they are still running. As in LockErrorCleanup,
1665 * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1666 * already caused QueryCancelPending to become set, we want the cancel to
1667 * be reported as a lock timeout, not a user cancel.
1668 */
1669 if (!InHotStandby)
1670 {
1671 if (LockTimeout > 0)
1672 {
1674
1676 timeouts[0].keep_indicator = false;
1677 timeouts[1].id = LOCK_TIMEOUT;
1678 timeouts[1].keep_indicator = true;
1680 }
1681 else
1683 }
1684
1685 /*
1686 * Emit the log message if recovery conflict on lock was resolved but the
1687 * startup process waited longer than deadlock_timeout for it.
1688 */
1692 NULL, false);
1693
1694 /*
1695 * We don't have to do anything else, because the awaker did all the
1696 * necessary updates of the lock table and MyProc. (The caller is
1697 * responsible for updating the local lock table.)
1698 */
1699 return myWaitStatus;
1700}
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition timestamp.c:1721
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1781
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1609
int64 TimestampTz
Definition timestamp.h:39
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
bool message_level_is_interesting(int elevel)
Definition elog.c:273
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition elog.c:1285
int errdetail_log(const char *fmt,...)
Definition elog.c:1264
#define LOG
Definition elog.h:31
#define WARNING
Definition elog.h:36
#define DEBUG1
Definition elog.h:30
return true
Definition isn.c:130
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition lmgr.c:1249
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition lock.c:3069
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4253
@ DS_BLOCKED_BY_AUTOVACUUM
Definition lock.h:516
@ DS_NO_DEADLOCK
Definition lock.h:513
@ DS_NOT_YET_CHECKED
Definition lock.h:512
@ DS_SOFT_DEADLOCK
Definition lock.h:514
#define AccessExclusiveLock
Definition lockdefs.h:43
@ LW_SHARED
Definition lwlock.h:113
void pfree(void *pointer)
Definition mcxt.c:1616
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define PROC_VACUUM_FOR_WRAPAROUND
Definition proc.h:61
ProcWaitStatus
Definition proc.h:141
@ PROCSIG_RECOVERY_CONFLICT_LOCK
Definition procsignal.h:44
bool log_lock_waits
Definition proc.c:64
void GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
Definition proc.c:1905
int DeadlockTimeout
Definition proc.c:58
static void CheckDeadLock(void)
Definition proc.c:1792
int LockTimeout
Definition proc.c:60
void CheckRecoveryConflictDeadlock(void)
Definition standby.c:904
bool log_recovery_conflict_waits
Definition standby.c:42
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 initStringInfo(StringInfo str)
Definition stringinfo.c:97
uint8 locktag_lockmethodid
Definition lock.h:173
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition timeout.c:560
TimestampTz get_timeout_start_time(TimeoutId id)
Definition timeout.c:813
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition timeout.c:685
void enable_timeouts(const EnableTimeoutParams *timeouts, int count)
Definition timeout.c:630
@ TMPARAM_AFTER
Definition timeout.h:53
#define PG_WAIT_LOCK
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET
#define kill(pid, sig)
Definition win32_port.h:490
bool RecoveryInProgress(void)
Definition xlog.c:6460
bool InRecovery
Definition xlogutils.c:50
#define InHotStandby
Definition xlogutils.h:60

References AccessExclusiveLock, appendStringInfo(), Assert, buf, CHECK_FOR_INTERRUPTS, CheckDeadLock(), CheckRecoveryConflictDeadlock(), deadlock_state, DEADLOCK_TIMEOUT, DeadlockTimeout, DEBUG1, DescribeLockTag(), disable_timeout(), disable_timeouts(), 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(), fb(), get_timeout_start_time(), GetAwaitedLock(), GetBlockingAutoVacuumPgproc(), GetCurrentTimestamp(), GetLockConflicts(), GetLockHoldersAndWaiters(), GetLockmodeName(), got_deadlock_timeout, EnableTimeoutParams::id, DisableTimeoutParams::id, InHotStandby, initStringInfo(), InRecovery, kill, LOCK_TIMEOUT, LockHashPartitionLock, LOCKTAG::locktag_lockmethodid, LockTimeout, LOG, log_lock_waits, log_recovery_conflict_waits, LogRecoveryConflict(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), message_level_is_interesting(), MyLatch, MyProc, MyProcPid, now(), pfree(), pg_atomic_write_u64(), PG_WAIT_LOCK, PROC_IS_AUTOVACUUM, PROC_VACUUM_FOR_WRAPAROUND, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_OK, PROC_WAIT_STATUS_WAITING, ProcGlobal, PROCSIG_RECOVERY_CONFLICT_LOCK, RecoveryInProgress(), ResetLatch(), ResolveRecoveryConflictWithLock(), PROC_HDR::statusFlags, LOCK::tag, TimestampDifference(), TimestampDifferenceExceeds(), TMPARAM_AFTER, WaitLatch(), PGPROC::waitStart, PGPROC::waitStatus, WARNING, WL_EXIT_ON_PM_DEATH, and WL_LATCH_SET.

Referenced by WaitOnLock().

◆ ProcWaitForSignal()

◆ ProcWakeup()

void ProcWakeup ( PGPROC proc,
ProcWaitStatus  waitStatus 
)

Definition at line 1716 of file proc.c.

1717{
1718 if (dlist_node_is_detached(&proc->links))
1719 return;
1720
1722
1723 /* Remove process from wait queue */
1725
1726 /* Clean up process' state and pass it the ok/fail signal */
1727 proc->waitLock = NULL;
1728 proc->waitProcLock = NULL;
1729 proc->waitStatus = waitStatus;
1731
1732 /* And awaken it */
1733 SetLatch(&proc->procLatch);
1734}
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(), fb(), 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 912 of file proc.c.

913{
914 Assert(MyProc != NULL);
916}
void ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:567

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

Referenced by InitProcessPhase2().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 758 of file proc.c.

759{
760 /* use volatile pointer to prevent code rearrangement */
761 volatile PROC_HDR *procglobal = ProcGlobal;
762
764}

References fb(), 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 83 of file proc.c.

Referenced by CheckDeadLock(), and ProcSleep().

◆ DeadlockTimeout

◆ got_deadlock_timeout

volatile sig_atomic_t got_deadlock_timeout
static

Definition at line 86 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 63 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

int LockTimeout = 0

Definition at line 60 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

bool log_lock_waits = true

Definition at line 64 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGPROC* MyProc = NULL

Definition at line 67 of file proc.c.

Referenced by _brin_parallel_build_main(), _bt_parallel_build_main(), _gin_parallel_build_main(), AbortTransaction(), AtEOSubXact_Namespace(), AtEOXact_Namespace(), AtEOXact_Snapshot(), attach_to_queues(), AutoVacWorkerMain(), AuxiliaryProcKill(), BaseInit(), BecomeLockGroupLeader(), BecomeLockGroupMember(), BufferLockAcquire(), BufferLockDequeueSelf(), BufferLockQueueSelf(), CheckDeadLock(), CommitTransaction(), ComputeXidHorizons(), ConditionVariableBroadcast(), consume_xids_common(), CountOtherDBBackends(), CreateReplicationSlot(), DefineIndex(), EndPrepare(), exec_eval_simple_expr(), exec_simple_check_plan(), exec_stmt_call(), ExecParallelGetReceiver(), ExecParallelSetupTupleQueues(), ExecWaitStmt(), ExportSnapshot(), FastPathGetRelationLockEntry(), FastPathGrantRelationLock(), FastPathUnGrantRelationLock(), FindLockCycleRecurseMember(), get_cast_hashentry(), GetCurrentVirtualXIDs(), GetLockConflicts(), GetNewTransactionId(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), GetSnapshotDataReuse(), GetStableLatestTransactionId(), heap_inplace_update_and_unlock(), InitAuxiliaryProcess(), InitBufferManagerAccess(), InitializeParallelDSM(), InitPostgres(), InitProcess(), InitProcessPhase2(), InitRecoveryTransactionEnvironment(), InitTempTableNamespace(), InitWalSender(), JoinWaitQueue(), lock_and_open_sequence(), LockAcquireExtended(), LockBufferInternal(), 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(), pg_truncate_visibility_map(), pgaio_init_backend(), pgstat_report_activity(), PhysicalReplicationSlotNewXmin(), PostPrepare_Locks(), PrepareTransaction(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcessStandbyHSFeedbackMessage(), ProcKill(), ProcReleaseLocks(), ProcSleep(), ProcWakeup(), RecordTransactionCommit(), RecordTransactionCommitPrepared(), ReinitializeParallelDSM(), RelationTruncate(), RemoveProcFromArray(), ReplicationSlotRelease(), ResolveRecoveryConflictWithLock(), set_indexsafe_procflags(), SetAuthenticatedUserId(), setup_dynamic_shared_memory(), shm_mq_attach(), shm_mq_detach_internal(), shm_mq_receive(), shm_mq_sendv(), shm_mq_wait_for_attach(), smgr_bulk_finish(), SnapBuildInitialSnapshot(), SnapshotResetXmin(), StartTransaction(), StartupDecodingContext(), SwitchBackToLocalLatch(), SwitchToSharedLatch(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepQueueInsert(), SyncRepWaitForLSN(), TerminateOtherDBBackends(), TransactionGroupUpdateXidStatus(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), TruncateMultiXact(), vacuum_rel(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), WaitXLogInsertionsToFinish(), write_csvlog(), write_jsonlog(), XidCacheRemoveRunningXids(), and XLogSaveBufferForHint().

◆ PreparedXactProcs

PGPROC* PreparedXactProcs = NULL

Definition at line 81 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ ProcStructLock

◆ StatementTimeout

int StatementTimeout = 0

Definition at line 59 of file proc.c.

Referenced by enable_statement_timeout().

◆ TransactionTimeout