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 "utils/wait_event.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 DeadLockState 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
 
PROC_HDRProcGlobal = NULL
 
NON_EXEC_STATIC PGPROCAuxiliaryProcs = NULL
 
PGPROCPreparedXactProcs = NULL
 
static volatile sig_atomic_t got_deadlock_timeout
 

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC * AuxiliaryPidGetProc ( int  pid)

Definition at line 1085 of file proc.c.

1086{
1087 PGPROC *result = NULL;
1088 int index;
1089
1090 if (pid == 0) /* never match dummy PGPROCs */
1091 return NULL;
1092
1093 for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1094 {
1095 PGPROC *proc = &AuxiliaryProcs[index];
1096
1097 if (proc->pid == pid)
1098 {
1099 result = proc;
1100 break;
1101 }
1102 }
1103 return result;
1104}
static int fb(int x)
#define NUM_AUXILIARY_PROCS
Definition proc.h:527
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition proc.c:72
Definition proc.h:176
int pid
Definition proc.h:189
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_get_backend_wait_event(), pg_stat_get_backend_wait_event_type(), pg_stat_reset_backend_stats(), and pgstat_fetch_stat_backend_by_pid().

◆ AuxiliaryProcKill()

static void AuxiliaryProcKill ( int  code,
Datum  arg 
)
static

Definition at line 1034 of file proc.c.

1035{
1036 int proctype = DatumGetInt32(arg);
1038 PGPROC *proc;
1039
1041
1042 /* not safe if forked by system(), etc. */
1043 if (MyProc->pid != (int) getpid())
1044 elog(PANIC, "AuxiliaryProcKill() called in child process");
1045
1047
1048 Assert(MyProc == auxproc);
1049
1050 /* Release any LW locks I am holding (see notes above) */
1052
1053 /* Cancel any pending condition variable sleep, too */
1055
1056 /* look at the equivalent ProcKill() code for comments */
1059
1060 proc = MyProc;
1061 MyProc = NULL;
1063 DisownLatch(&proc->procLatch);
1064
1066
1067 /* Mark auxiliary proc no longer in use */
1068 proc->pid = 0;
1071
1072 /* Update shared estimate of spins_per_delay */
1074
1076}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:235
#define Assert(condition)
Definition c.h:906
bool ConditionVariableCancelSleep(void)
Datum arg
Definition elog.c:1322
#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:1893
void SwitchBackToLocalLatch(void)
Definition miscinit.c:243
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
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56
PGPROC * MyProc
Definition proc.c:68
PROC_HDR * ProcGlobal
Definition proc.c:71
LocalTransactionId lxid
Definition proc.h:223
struct PGPROC::@133 vxid
ProcNumber procNumber
Definition proc.h:218
Latch procLatch
Definition proc.h:248
slock_t freeProcsLock
Definition proc.h:468
int spins_per_delay
Definition proc.h:492
#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(), PROC_HDR::freeProcsLock, 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, 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 2000 of file proc.c.

2001{
2003
2004 /* If we already did it, we don't need to do it again. */
2006 return;
2007
2008 /* We had better not be a follower. */
2010
2011 /* Create single-member group, containing only ourselves. */
2017}
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:1177
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794
@ LW_EXCLUSIVE
Definition lwlock.h:112
dlist_head lockGroupMembers
Definition proc.h:291
dlist_node lockGroupLink
Definition proc.h:292
PGPROC * lockGroupLeader
Definition proc.h:290

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 2030 of file proc.c.

2031{
2033 bool ok = false;
2034
2035 /* Group leader can't become member of group */
2036 Assert(MyProc != leader);
2037
2038 /* Can't already be a member of a group */
2040
2041 /* PID must be valid. */
2042 Assert(pid != 0);
2043
2044 /*
2045 * Get lock protecting the group fields. Note LockHashPartitionLockByProc
2046 * calculates the proc number based on the PGPROC slot without looking at
2047 * its contents, so we will acquire the correct lock even if the leader
2048 * PGPROC is in process of being recycled.
2049 */
2052
2053 /* Is this the leader we're looking for? */
2054 if (leader->pid == pid && leader->lockGroupLeader == leader)
2055 {
2056 /* OK, join the group */
2057 ok = true;
2058 MyProc->lockGroupLeader = leader;
2060 }
2062
2063 return ok;
2064}
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 DeadLockState CheckDeadLock ( void  )
static

Definition at line 1781 of file proc.c.

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

References Assert, DeadLockCheck(), dlist_node_is_detached(), DS_HARD_DEADLOCK, DS_NO_DEADLOCK, fb(), i, LockHashPartitionLockByIndex, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, NUM_LOCK_PARTITIONS, RemoveFromWaitQueue(), LOCK::tag, PGPROC::waitLink, and PGPROC::waitLock.

Referenced by ProcSleep().

◆ CheckDeadLockAlert()

void CheckDeadLockAlert ( void  )

Definition at line 1872 of file proc.c.

1873{
1874 int save_errno = errno;
1875
1876 got_deadlock_timeout = true;
1877
1878 /*
1879 * Have to set the latch again, even if handle_sig_alarm already did. Back
1880 * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1881 * ever would be a problem, but setting a set latch again is cheap.
1882 *
1883 * Note that, when this function runs inside procsignal_sigusr1_handler(),
1884 * the handler function sets the latch again after the latch is set here.
1885 */
1887 errno = save_errno;
1888}
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:76

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

Referenced by InitPostgres(), and ProcessRecoveryConflictInterrupt().

◆ FastPathLockShmemSize()

static Size FastPathLockShmemSize ( void  )
static

Definition at line 106 of file proc.c.

107{
108 Size size = 0;
113
114 /*
115 * Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are
116 * nicely aligned in each backend.
117 */
120
122
123 return size;
124}
#define MAXALIGN(LEN)
Definition c.h:859
uint64_t uint64
Definition c.h:580
size_t Size
Definition c.h:652
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:117

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 1899 of file proc.c.

1901{
1904 LOCK *lock = locallock->lock;
1905 bool first_holder = true,
1906 first_waiter = true;
1907
1908#ifdef USE_ASSERT_CHECKING
1909 {
1910 uint32 hashcode = locallock->hashcode;
1912
1914 }
1915#endif
1916
1917 *lockHoldersNum = 0;
1918
1919 /*
1920 * Loop over the lock's procLocks to gather a list of all holders and
1921 * waiters. Thus we will be able to provide more detailed information for
1922 * lock debugging purposes.
1923 *
1924 * lock->procLocks contains all processes which hold or wait for this
1925 * lock.
1926 */
1928 {
1929 curproclock =
1930 dlist_container(PROCLOCK, lockLink, proc_iter.cur);
1931
1932 /*
1933 * We are a waiter if myProc->waitProcLock == curproclock; we are a
1934 * holder if it is NULL or something different.
1935 */
1936 if (curproclock->tag.myProc->waitProcLock == curproclock)
1937 {
1938 if (first_waiter)
1939 {
1941 curproclock->tag.myProc->pid);
1942 first_waiter = false;
1943 }
1944 else
1946 curproclock->tag.myProc->pid);
1947 }
1948 else
1949 {
1950 if (first_holder)
1951 {
1953 curproclock->tag.myProc->pid);
1954 first_holder = false;
1955 }
1956 else
1958 curproclock->tag.myProc->pid);
1959
1960 (*lockHoldersNum)++;
1961 }
1962 }
1963}
uint32_t uint32
Definition c.h:579
#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:1912
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 759 of file proc.c.

760{
761 /* use volatile pointer to prevent code rearrangement */
762 volatile PROC_HDR *procglobal = ProcGlobal;
763
765}
int startupBufferPinWaitBufId
Definition proc.h:494

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

Referenced by HoldingBufferPinThatDelaysRecovery().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int nfree 
)

Definition at line 775 of file proc.c.

776{
777 dlist_iter iter;
778
779 Assert(n > 0);
780 Assert(nfree);
781
783
784 *nfree = 0;
786 {
787 (*nfree)++;
788 if (*nfree == n)
789 break;
790 }
791
793
794 return (*nfree == n);
795}
dlist_head freeProcs
Definition proc.h:471

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 606 of file proc.c.

607{
609 int proctype;
610
611 /*
612 * ProcGlobal should be set up already (if we are a backend, we inherit
613 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
614 */
615 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
616 elog(PANIC, "proc header uninitialized");
617
618 if (MyProc != NULL)
619 elog(ERROR, "you already exist");
620
623
624 /*
625 * We use the freeProcsLock to protect assignment and releasing of
626 * AuxiliaryProcs entries.
627 *
628 * While we are holding the spinlock, also copy the current shared
629 * estimate of spins_per_delay to local storage.
630 */
632
634
635 /*
636 * Find a free auxproc ... *big* trouble if there isn't one ...
637 */
639 {
641 if (auxproc->pid == 0)
642 break;
643 }
645 {
647 elog(FATAL, "all AuxiliaryProcs are in use");
648 }
649
650 /* Mark auxiliary proc as in use by me */
651 /* use volatile pointer to prevent code rearrangement */
652 ((volatile PGPROC *) auxproc)->pid = MyProcPid;
653
655
656 MyProc = auxproc;
658
659 /*
660 * Initialize all fields of MyProc, except for those previously
661 * initialized by InitProcGlobal.
662 */
665 MyProc->fpVXIDLock = false;
676 MyProc->statusFlags = 0;
678 MyProc->lwWaitMode = 0;
683#ifdef USE_ASSERT_CHECKING
684 {
685 int i;
686
687 /* Last process should have released all locks. */
688 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
690 }
691#endif
693
694 /*
695 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
696 * on it. That allows us to repoint the process latch, which so far
697 * points to process local one, to the shared one.
698 */
701
702 /* now that we have a proc, report wait events to shared memory */
704
705 /* Check that group locking fields are in a proper initial state. */
708
709 /*
710 * We might be reusing a semaphore that belonged to a failed process. So
711 * be careful and reinitialize its value here. (This is not strictly
712 * necessary anymore, but seems like a good idea for cleanliness.)
713 */
715
716 /*
717 * Arrange to clean up at process exit.
718 */
720
721 /*
722 * Now that we have a PGPROC, we could try to acquire lightweight locks.
723 * Initialize local state needed for them. (Heavyweight locks cannot be
724 * acquired in aux processes.)
725 */
727
728#ifdef EXEC_BACKEND
729
730 /*
731 * Initialize backend-local pointers to all the shared data structures.
732 * (We couldn't do this until now because it needs LWLocks.)
733 */
736#endif
737}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:485
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:274
#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:551
@ LW_WS_NOT_WAITING
Definition lwlock.h:30
void SwitchToSharedLatch(void)
Definition miscinit.c:216
BackendType MyBackendType
Definition miscinit.c:65
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:505
@ 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:1034
TransactionId xmin
Definition proc.h:234
PROCLOCK * waitProcLock
Definition proc.h:298
dlist_node freeProcsLink
Definition proc.h:178
uint8 lwWaitMode
Definition proc.h:276
uint32 wait_event_info
Definition proc.h:370
BackendType backendType
Definition proc.h:190
uint8 statusFlags
Definition proc.h:202
Oid databaseId
Definition proc.h:193
pg_atomic_uint64 waitStart
Definition proc.h:303
bool fpVXIDLock
Definition proc.h:319
TransactionId xid
Definition proc.h:229
int delayChkptFlags
Definition proc.h:252
pg_atomic_uint32 pendingRecoveryConflicts
Definition proc.h:262
LocalTransactionId fpLocalTransactionId
Definition proc.h:320
PGSemaphore sem
Definition proc.h:250
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition proc.h:313
Oid roleId
Definition proc.h:194
ProcWaitStatus waitStatus
Definition proc.h:306
Oid tempNamespaceId
Definition proc.h:196
uint8 lwWaiting
Definition proc.h:275
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, PGPROC::freeProcsLink, PROC_HDR::freeProcsLock, GetNumberFromPGProc, i, InitLWLockAccess(), Int32GetDatum(), INVALID_PROC_NUMBER, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, IsUnderPostmaster, 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, PGPROC::pendingRecoveryConflicts, pg_atomic_write_u32(), pg_atomic_write_u64(), PGSemaphoreReset(), pgstat_set_wait_event_storage(), PROC_WAIT_STATUS_OK, ProcGlobal, PGPROC::procLatch, PGPROC::procNumber, 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::waitLink, PGPROC::waitLock, PGPROC::waitProcLock, PGPROC::waitStart, PGPROC::waitStatus, PGPROC::xid, and PGPROC::xmin.

Referenced by AuxiliaryProcessMainCommon().

◆ InitProcess()

void InitProcess ( void  )

Definition at line 380 of file proc.c.

381{
382 dlist_head *procgloballist;
383
384 /*
385 * ProcGlobal should be set up already (if we are a backend, we inherit
386 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
387 */
388 if (ProcGlobal == NULL)
389 elog(PANIC, "proc header uninitialized");
390
391 if (MyProc != NULL)
392 elog(ERROR, "you already exist");
393
394 /*
395 * Before we start accessing the shared memory in a serious way, mark
396 * ourselves as an active postmaster child; this is so that the postmaster
397 * can detect it if we exit without cleaning up.
398 */
401
402 /*
403 * Decide which list should supply our PGPROC. This logic must match the
404 * way the freelists were constructed in InitProcGlobal().
405 */
407 procgloballist = &ProcGlobal->autovacFreeProcs;
408 else if (AmBackgroundWorkerProcess())
409 procgloballist = &ProcGlobal->bgworkerFreeProcs;
410 else if (AmWalSenderProcess())
411 procgloballist = &ProcGlobal->walsenderFreeProcs;
412 else
413 procgloballist = &ProcGlobal->freeProcs;
414
415 /*
416 * Try to get a proc struct from the appropriate free list. If this
417 * fails, we must be out of PGPROC structures (not to mention semaphores).
418 *
419 * While we are holding the spinlock, also copy the current shared
420 * estimate of spins_per_delay to local storage.
421 */
423
425
426 if (!dlist_is_empty(procgloballist))
427 {
428 MyProc = dlist_container(PGPROC, freeProcsLink, dlist_pop_head_node(procgloballist));
430 }
431 else
432 {
433 /*
434 * If we reach here, all the PGPROCs are in use. This is one of the
435 * possible places to detect "too many backends", so give the standard
436 * error message. XXX do we need to give a different failure message
437 * in the autovacuum case?
438 */
440 if (AmWalSenderProcess())
443 errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
447 errmsg("sorry, too many clients already")));
448 }
450
451 /*
452 * Cross-check that the PGPROC is of the type we expect; if this were not
453 * the case, it would get returned to the wrong list.
454 */
455 Assert(MyProc->procgloballist == procgloballist);
456
457 /*
458 * Initialize all fields of MyProc, except for those previously
459 * initialized by InitProcGlobal.
460 */
463 MyProc->fpVXIDLock = false;
470 /* databaseId and roleId will be filled in later */
476 MyProc->statusFlags = 0;
477 /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
481 MyProc->lwWaitMode = 0;
486#ifdef USE_ASSERT_CHECKING
487 {
488 int i;
489
490 /* Last process should have released all locks. */
491 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
493 }
494#endif
496
497 /* Initialize fields for sync rep */
501
502 /* Initialize fields for group XID clearing. */
506
507 /* Check that group locking fields are in a proper initial state. */
510
511 /* Initialize wait event information. */
513
514 /* Initialize fields for group transaction status update. */
515 MyProc->clogGroupMember = false;
521
522 /*
523 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
524 * on it. That allows us to repoint the process latch, which so far
525 * points to process local one, to the shared one.
526 */
529
530 /* now that we have a proc, report wait events to shared memory */
532
533 /*
534 * We might be reusing a semaphore that belonged to a failed process. So
535 * be careful and reinitialize its value here. (This is not strictly
536 * necessary anymore, but seems like a good idea for cleanliness.)
537 */
539
540 /*
541 * Arrange to clean up at backend exit.
542 */
544
545 /*
546 * Now that we have a PGPROC, we could try to acquire locks, so initialize
547 * local state needed for LWLocks, and the deadlock checker.
548 */
551
552#ifdef EXEC_BACKEND
553
554 /*
555 * Initialize backend-local pointers to all the shared data structures.
556 * (We couldn't do this until now because it needs LWLocks.)
557 */
560#endif
561}
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:143
int errcode(int sqlerrcode)
Definition elog.c:874
#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
static char * errmsg
#define PROC_IS_AUTOVACUUM
Definition proc.h:58
static void ProcKill(int code, Datum arg)
Definition proc.c:912
bool procArrayGroupMember
Definition proc.h:342
XLogRecPtr clogGroupMemberLsn
Definition proc.h:363
pg_atomic_uint32 procArrayGroupNext
Definition proc.h:344
dlist_head * procgloballist
Definition proc.h:177
TransactionId clogGroupMemberXid
Definition proc.h:358
int64 clogGroupMemberPage
Definition proc.h:361
bool clogGroupMember
Definition proc.h:356
XLogRecPtr waitLSN
Definition proc.h:333
dlist_node syncRepLinks
Definition proc.h:335
int syncRepState
Definition proc.h:334
pg_atomic_uint32 clogGroupNext
Definition proc.h:357
XidStatus clogGroupMemberXidStatus
Definition proc.h:359
TransactionId procArrayGroupMemberXid
Definition proc.h:350
dlist_head autovacFreeProcs
Definition proc.h:473
dlist_head walsenderFreeProcs
Definition proc.h:477
dlist_head bgworkerFreeProcs
Definition proc.h:475
#define SYNC_REP_NOT_WAITING
Definition syncrep.h:30
int max_wal_senders
Definition walsender.c:130
#define InvalidXLogRecPtr
Definition xlogdefs.h:28

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, PGPROC::freeProcsLink, PROC_HDR::freeProcsLock, GetNumberFromPGProc, i, InitDeadLockChecking(), InitLWLockAccess(), INVALID_PROC_NUMBER, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsUnderPostmaster, 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, PGPROC::pendingRecoveryConflicts, pg_atomic_read_u32(), pg_atomic_write_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, 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::waitLink, 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 571 of file proc.c.

572{
573 Assert(MyProc != NULL);
574
575 /*
576 * Add our PGPROC to the PGPROC array in shared memory.
577 */
579
580 /*
581 * Arrange to clean that up at backend exit.
582 */
584}
void ProcArrayAdd(PGPROC *proc)
Definition procarray.c:472
static void RemoveProcFromArray(int code, Datum arg)
Definition proc.c:901

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 184 of file proc.c.

185{
186 PGPROC *procs;
187 int i,
188 j;
189 bool found;
191
192 /* Used for setup of per-backend fast-path slots. */
193 char *fpPtr,
198 char *ptr;
199
200 /* Create the ProcGlobal shared structure */
201 ProcGlobal = (PROC_HDR *)
202 ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
203 Assert(!found);
204
205 /*
206 * Initialize the data structures.
207 */
219
220 /*
221 * Create and initialize all the PGPROC structures we'll need. There are
222 * six separate consumers: (1) normal backends, (2) autovacuum workers and
223 * special workers, (3) background workers, (4) walsenders, (5) auxiliary
224 * processes, and (6) prepared transactions. (For largely-historical
225 * reasons, we combine autovacuum and special workers into one category
226 * with a single freelist.) Each PGPROC structure is dedicated to exactly
227 * one of these purposes, and they do not move between groups.
228 */
230
231 ptr = ShmemInitStruct("PGPROC structures",
233 &found);
234
235 MemSet(ptr, 0, requestSize);
236
237 procs = (PGPROC *) ptr;
238 ptr = ptr + TotalProcs * sizeof(PGPROC);
239
240 ProcGlobal->allProcs = procs;
241 /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
243
244 /*
245 * Allocate arrays mirroring PGPROC fields in a dense manner. See
246 * PROC_HDR.
247 *
248 * XXX: It might make sense to increase padding for these arrays, given
249 * how hotly they are accessed.
250 */
251 ProcGlobal->xids = (TransactionId *) ptr;
252 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
253
255 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
256
257 ProcGlobal->statusFlags = (uint8 *) ptr;
258 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
259
260 /* make sure wer didn't overflow */
261 Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
262
263 /*
264 * Allocate arrays for fast-path locks. Those are variable-length, so
265 * can't be included in PGPROC directly. We allocate a separate piece of
266 * shared memory and then divide that between backends.
267 */
270
272
273 fpPtr = ShmemInitStruct("Fast-Path Lock Array",
275 &found);
276
278
279 /* For asserts checking we did not overflow. */
281
282 /* Reserve space for semaphores. */
284
285 for (i = 0; i < TotalProcs; i++)
286 {
287 PGPROC *proc = &procs[i];
288
289 /* Common initialization for all PGPROCs, regardless of type. */
290
291 /*
292 * Set the fast-path lock arrays, and move the pointer. We interleave
293 * the two arrays, to (hopefully) get some locality for each backend.
294 */
295 proc->fpLockBits = (uint64 *) fpPtr;
297
298 proc->fpRelId = (Oid *) fpPtr;
300
302
303 /*
304 * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
305 * dummy PGPROCs don't need these though - they're never associated
306 * with a real process
307 */
309 {
310 proc->sem = PGSemaphoreCreate();
311 InitSharedLatch(&(proc->procLatch));
313 }
314
315 /*
316 * Newly created PGPROCs for normal backends, autovacuum workers,
317 * special workers, bgworkers, and walsenders must be queued up on the
318 * appropriate free list. Because there can only ever be a small,
319 * fixed number of auxiliary processes, no free list is used in that
320 * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs
321 * for prepared transactions are added to a free list by
322 * TwoPhaseShmemInit().
323 */
324 if (i < MaxConnections)
325 {
326 /* PGPROC for normal backend, add to freeProcs list */
329 }
331 {
332 /* PGPROC for AV or special worker, add to autovacFreeProcs list */
335 }
337 {
338 /* PGPROC for bgworker, add to bgworkerFreeProcs list */
341 }
342 else if (i < MaxBackends)
343 {
344 /* PGPROC for walsender, add to walsenderFreeProcs list */
347 }
348
349 /* Initialize myProcLocks[] shared memory queues. */
350 for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
351 dlist_init(&(proc->myProcLocks[j]));
352
353 /* Initialize lockGroupMembers list. */
355
356 /*
357 * Initialize the atomic variables, otherwise, it won't be safe to
358 * access them for backends that aren't currently in use.
359 */
362 pg_atomic_init_u64(&(proc->waitStart), 0);
363 }
364
365 /* Should have consumed exactly the expected amount of fast-path memory. */
367
368 /*
369 * Save pointers to the blocks of PGPROC structures reserved for auxiliary
370 * processes and prepared transactions.
371 */
372 AuxiliaryProcs = &procs[MaxBackends];
374}
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:119
uint8_t uint8
Definition c.h:577
#define MemSet(start, val, len)
Definition c.h:1070
uint32 TransactionId
Definition c.h:699
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:699
void PGReserveSemaphores(int maxSemas)
Definition posix_sema.c:196
PGSemaphore PGSemaphoreCreate(void)
Definition posix_sema.c:257
#define FIRST_PREPARED_XACT_PROC_NUMBER
Definition proc.h:529
#define NUM_SPECIAL_WORKER_PROCS
Definition proc.h:514
#define DEFAULT_SPINS_PER_DELAY
Definition s_lock.h:718
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
static void SpinLockInit(volatile slock_t *lock)
Definition spin.h:50
PGPROC * PreparedXactProcs
Definition proc.c:73
static Size PGProcShmemSize(void)
Definition proc.c:88
static Size FastPathLockShmemSize(void)
Definition proc.c:106
int ProcGlobalSemas(void)
Definition proc.c:149
LWLock fpInfoLock
Definition proc.h:316
Oid * fpRelId
Definition proc.h:318
uint64 * fpLockBits
Definition proc.h:317
uint8 * statusFlags
Definition proc.h:456
XidCacheStatus * subxidStates
Definition proc.h:450
ProcNumber checkpointerProc
Definition proc.h:489
PGPROC * allProcs
Definition proc.h:441
pg_atomic_uint32 clogGroupFirst
Definition proc.h:482
TransactionId * xids
Definition proc.h:444
ProcNumber walwriterProc
Definition proc.h:488
pg_atomic_uint32 procArrayGroupFirst
Definition proc.h:480
uint32 allProcCount
Definition proc.h:459

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(), FIRST_PREPARED_XACT_PROC_NUMBER, PGPROC::fpInfoLock, PGPROC::fpLockBits, PGPROC::fpRelId, PROC_HDR::freeProcs, PGPROC::freeProcsLink, PROC_HDR::freeProcsLock, i, InitSharedLatch(), INVALID_PROC_NUMBER, j, 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, 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 1134 of file proc.c.

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

Referenced by LockAcquireExtended().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 806 of file proc.c.

807{
811
813
815
816 /* Nothing to do if we weren't waiting for a lock */
818 if (lockAwaited == NULL)
819 {
821 return;
822 }
823
824 /*
825 * Turn off the deadlock and lock timeout timers, if they are still
826 * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
827 * indicator flag, since this function is executed before
828 * ProcessInterrupts when responding to SIGINT; else we'd lose the
829 * knowledge that the SIGINT came from a lock timeout and not an external
830 * source.
831 */
833 timeouts[0].keep_indicator = false;
834 timeouts[1].id = LOCK_TIMEOUT;
835 timeouts[1].keep_indicator = true;
837
838 /* Unlink myself from the wait queue, if on it (might not be anymore!) */
841
843 {
844 /* We could not have been granted the lock yet */
846 }
847 else
848 {
849 /*
850 * Somebody kicked us off the lock queue already. Perhaps they
851 * granted us the lock, or perhaps they detected a deadlock. If they
852 * did grant us the lock, we'd better remember it in our local lock
853 * table.
854 */
857 }
858
860
862
864}
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, LOCK_TIMEOUT, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), ResetAwaitedLock(), RESUME_INTERRUPTS, PGPROC::waitLink, and PGPROC::waitStatus.

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

◆ PGProcShmemSize()

static Size PGProcShmemSize ( void  )
static

Definition at line 88 of file proc.c.

89{
90 Size size = 0;
93
94 size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
95 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
96 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
97 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
98
99 return size;
100}

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 149 of file proc.c.

150{
151 /*
152 * We need a sema per backend (including autovacuum), plus one for each
153 * auxiliary process.
154 */
156}

References MaxBackends, and NUM_AUXILIARY_PROCS.

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

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 130 of file proc.c.

131{
132 Size size = 0;
133
134 /* ProcGlobal */
135 size = add_size(size, sizeof(PROC_HDR));
136 size = add_size(size, sizeof(slock_t));
137
139 size = add_size(size, PGProcShmemSize());
140 size = add_size(size, FastPathLockShmemSize());
141
142 return size;
143}
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 912 of file proc.c.

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

References Assert, ConditionVariableCancelSleep(), DisownLatch(), dlist_delete(), dlist_is_empty(), dlist_push_head(), dlist_push_tail(), elog, fb(), PGPROC::freeProcsLink, PROC_HDR::freeProcsLock, i, INVALID_PROC_NUMBER, InvalidTransactionId, 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, 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 1734 of file proc.c.

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

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

885{
886 if (!MyProc)
887 return;
888 /* If waiting, get off wait queue (should only be needed after error) */
890 /* Release standard locks, including session-level if aborting */
892 /* Release transaction-level advisory locks */
894}
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:806

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 1985 of file proc.c.

1986{
1988 elog(ERROR, "procNumber out of range");
1989
1990 SetLatch(&GetPGProcByNumber(procNumber)->procLatch);
1991}
#define GetPGProcByNumber(n)
Definition proc.h:504

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

Referenced by ReleasePredicateLocks(), and WakePinCountWaiter().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock)

Definition at line 1303 of file proc.c.

1304{
1305 LOCKMODE lockmode = locallock->tag.mode;
1306 LOCK *lock = locallock->lock;
1307 uint32 hashcode = locallock->hashcode;
1310 bool allow_autovacuum_cancel = true;
1311 bool logged_recovery_conflict = false;
1314
1315 /* The caller must've armed the on-error cleanup mechanism */
1318
1319 /*
1320 * Now that we will successfully clean up after an ereport, it's safe to
1321 * check to see if there's a buffer pin deadlock against the Startup
1322 * process. Of course, that's only necessary if we're doing Hot Standby
1323 * and are not the Startup process ourselves.
1324 */
1327
1328 /* Reset deadlock_state before enabling the timeout handler */
1330 got_deadlock_timeout = false;
1331
1332 /*
1333 * Set timer so we can wake up after awhile and check for a deadlock. If a
1334 * deadlock is detected, the handler sets MyProc->waitStatus =
1335 * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
1336 * rather than success.
1337 *
1338 * By delaying the check until we've waited for a bit, we can avoid
1339 * running the rather expensive deadlock-check code in most cases.
1340 *
1341 * If LockTimeout is set, also enable the timeout for that. We can save a
1342 * few cycles by enabling both timeout sources in one call.
1343 *
1344 * If InHotStandby we set lock waits slightly later for clarity with other
1345 * code.
1346 */
1347 if (!InHotStandby)
1348 {
1349 if (LockTimeout > 0)
1350 {
1352
1354 timeouts[0].type = TMPARAM_AFTER;
1355 timeouts[0].delay_ms = DeadlockTimeout;
1356 timeouts[1].id = LOCK_TIMEOUT;
1357 timeouts[1].type = TMPARAM_AFTER;
1358 timeouts[1].delay_ms = LockTimeout;
1360 }
1361 else
1363
1364 /*
1365 * Use the current time obtained for the deadlock timeout timer as
1366 * waitStart (i.e., the time when this process started waiting for the
1367 * lock). Since getting the current time newly can cause overhead, we
1368 * reuse the already-obtained time to avoid that overhead.
1369 *
1370 * Note that waitStart is updated without holding the lock table's
1371 * partition lock, to avoid the overhead by additional lock
1372 * acquisition. This can cause "waitstart" in pg_locks to become NULL
1373 * for a very short period of time after the wait started even though
1374 * "granted" is false. This is OK in practice because we can assume
1375 * that users are likely to look at "waitstart" when waiting for the
1376 * lock for a long time.
1377 */
1380 }
1382 {
1383 /*
1384 * Set the wait start timestamp if logging is enabled and in hot
1385 * standby.
1386 */
1388 }
1389
1390 /*
1391 * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1392 * will not wait. But a set latch does not necessarily mean that the lock
1393 * is free now, as there are many other sources for latch sets than
1394 * somebody releasing the lock.
1395 *
1396 * We process interrupts whenever the latch has been set, so cancel/die
1397 * interrupts are processed quickly. This means we must not mind losing
1398 * control to a cancel/die interrupt here. We don't, because we have no
1399 * shared-state-change work to do after being granted the lock (the
1400 * grantor did it all). We do have to worry about canceling the deadlock
1401 * timeout and updating the locallock table, but if we lose control to an
1402 * error, LockErrorCleanup will fix that up.
1403 */
1404 do
1405 {
1406 if (InHotStandby)
1407 {
1408 bool maybe_log_conflict =
1410
1411 /* Set a timer and wait for that or for the lock to be granted */
1414
1415 /*
1416 * Emit the log message if the startup process is waiting longer
1417 * than deadlock_timeout for recovery conflict on lock.
1418 */
1420 {
1422
1425 {
1427 int cnt;
1428
1429 vxids = GetLockConflicts(&locallock->tag.lock,
1430 AccessExclusiveLock, &cnt);
1431
1432 /*
1433 * Log the recovery conflict and the list of PIDs of
1434 * backends holding the conflicting lock. Note that we do
1435 * logging even if there are no such backends right now
1436 * because the startup process here has already waited
1437 * longer than deadlock_timeout.
1438 */
1441 cnt > 0 ? vxids : NULL, true);
1443 }
1444 }
1445 }
1446 else
1447 {
1449 PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1451 /* check for deadlocks first, as that's probably log-worthy */
1453 {
1455 got_deadlock_timeout = false;
1456 }
1458 }
1459
1460 /*
1461 * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
1462 * else asynchronously. Read it just once per loop to prevent
1463 * surprising behavior (such as missing log messages).
1464 */
1465 myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
1466
1467 /*
1468 * If we are not deadlocked, but are waiting on an autovacuum-induced
1469 * task, send a signal to interrupt it.
1470 */
1472 {
1474 uint8 statusFlags;
1477
1478 /*
1479 * Grab info we need, then release lock immediately. Note this
1480 * coding means that there is a tiny chance that the process
1481 * terminates its current transaction and starts a different one
1482 * before we have a change to send the signal; the worst possible
1483 * consequence is that a for-wraparound vacuum is canceled. But
1484 * that could happen in any case unless we were to do kill() with
1485 * the lock held, which is much more undesirable.
1486 */
1488 statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1490 locktag_copy = lock->tag;
1492
1493 /*
1494 * Only do it if the worker is not working to protect against Xid
1495 * wraparound.
1496 */
1497 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
1498 !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
1499 {
1500 int pid = autovac->pid;
1501
1502 /* report the case, if configured to do so */
1504 {
1506 StringInfoData logbuf; /* errdetail for server log */
1507
1512 "Process %d waits for %s on %s.",
1513 MyProcPid,
1515 locktagbuf.data);
1516
1518 (errmsg_internal("sending cancel to blocking autovacuum PID %d",
1519 pid),
1520 errdetail_log("%s", logbuf.data)));
1521
1522 pfree(locktagbuf.data);
1523 pfree(logbuf.data);
1524 }
1525
1526 /* send the autovacuum worker Back to Old Kent Road */
1527 if (kill(pid, SIGINT) < 0)
1528 {
1529 /*
1530 * There's a race condition here: once we release the
1531 * ProcArrayLock, it's possible for the autovac worker to
1532 * close up shop and exit before we can do the kill().
1533 * Therefore, we do not whinge about no-such-process.
1534 * Other errors such as EPERM could conceivably happen if
1535 * the kernel recycles the PID fast enough, but such cases
1536 * seem improbable enough that it's probably best to issue
1537 * a warning if we see some other errno.
1538 */
1539 if (errno != ESRCH)
1541 (errmsg("could not send signal to process %d: %m",
1542 pid)));
1543 }
1544 }
1545
1546 /* prevent signal from being sent again more than once */
1548 }
1549
1550 /*
1551 * If awoken after the deadlock check interrupt has run, and
1552 * log_lock_waits is on, then report about the wait.
1553 */
1555 {
1559 const char *modename;
1560 long secs;
1561 int usecs;
1562 long msecs;
1563 int lockHoldersNum = 0;
1564
1568
1569 DescribeLockTag(&buf, &locallock->tag.lock);
1570 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1571 lockmode);
1574 &secs, &usecs);
1575 msecs = secs * 1000 + usecs / 1000;
1576 usecs = usecs % 1000;
1577
1578 /* Gather a list of all lock holders and waiters */
1583
1585 ereport(LOG,
1586 (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1587 MyProcPid, modename, buf.data, msecs, usecs),
1588 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1589 "Processes holding the lock: %s. Wait queue: %s.",
1591 else if (deadlock_state == DS_HARD_DEADLOCK)
1592 {
1593 /*
1594 * This message is a bit redundant with the error that will be
1595 * reported subsequently, but in some cases the error report
1596 * might not make it to the log (eg, if it's caught by an
1597 * exception handler), and we want to ensure all long-wait
1598 * events get logged.
1599 */
1600 ereport(LOG,
1601 (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1602 MyProcPid, modename, buf.data, msecs, usecs),
1603 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1604 "Processes holding the lock: %s. Wait queue: %s.",
1606 }
1607
1609 ereport(LOG,
1610 (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1611 MyProcPid, modename, buf.data, msecs, usecs),
1612 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1613 "Processes holding the lock: %s. Wait queue: %s.",
1616 ereport(LOG,
1617 (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1618 MyProcPid, modename, buf.data, msecs, usecs)));
1619 else
1620 {
1622
1623 /*
1624 * Currently, the deadlock checker always kicks its own
1625 * process, which means that we'll only see
1626 * PROC_WAIT_STATUS_ERROR when deadlock_state ==
1627 * DS_HARD_DEADLOCK, and there's no need to print redundant
1628 * messages. But for completeness and future-proofing, print
1629 * a message if it looks like someone else kicked us off the
1630 * lock.
1631 */
1633 ereport(LOG,
1634 (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1635 MyProcPid, modename, buf.data, msecs, usecs),
1636 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1637 "Processes holding the lock: %s. Wait queue: %s.",
1639 }
1640
1641 /*
1642 * At this point we might still need to wait for the lock. Reset
1643 * state so we don't print the above messages again.
1644 */
1646
1647 pfree(buf.data);
1650 }
1652
1653 /*
1654 * Disable the timers, if they are still running. As in LockErrorCleanup,
1655 * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1656 * already caused QueryCancelPending to become set, we want the cancel to
1657 * be reported as a lock timeout, not a user cancel.
1658 */
1659 if (!InHotStandby)
1660 {
1661 if (LockTimeout > 0)
1662 {
1664
1666 timeouts[0].keep_indicator = false;
1667 timeouts[1].id = LOCK_TIMEOUT;
1668 timeouts[1].keep_indicator = true;
1670 }
1671 else
1673 }
1674
1675 /*
1676 * Emit the log message if recovery conflict on lock was resolved but the
1677 * startup process waited longer than deadlock_timeout for it.
1678 */
1682 NULL, false);
1683
1684 /*
1685 * We don't have to do anything else, because the awaker did all the
1686 * necessary updates of the lock table and MyProc. (The caller is
1687 * responsible for updating the local lock table.)
1688 */
1689 return myWaitStatus;
1690}
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition timestamp.c:1719
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1779
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1643
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1607
int64 TimestampTz
Definition timestamp.h:39
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
bool message_level_is_interesting(int elevel)
Definition elog.c:284
#define LOG
Definition elog.h:31
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:36
#define DEBUG1
Definition elog.h:30
int int int errdetail_log(const char *fmt,...) pg_attribute_printf(1
int int int int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
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:4252
@ DS_BLOCKED_BY_AUTOVACUUM
Definition lock.h:516
@ 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
bool log_lock_waits
Definition proc.c:65
void GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
Definition proc.c:1899
int DeadlockTimeout
Definition proc.c:59
int LockTimeout
Definition proc.c:61
static DeadLockState CheckDeadLock(void)
Definition proc.c:1781
void CheckRecoveryConflictDeadlock(void)
Definition standby.c:906
bool log_recovery_conflict_waits
Definition standby.c:43
void LogRecoveryConflict(RecoveryConflictReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition standby.c:275
void ResolveRecoveryConflictWithLock(LOCKTAG locktag, bool logging_conflict)
Definition standby.c:625
@ RECOVERY_CONFLICT_LOCK
Definition standby.h:37
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:6444
bool InRecovery
Definition xlogutils.c:50
#define InHotStandby
Definition xlogutils.h:60

References AccessExclusiveLock, appendStringInfo(), Assert, buf, CHECK_FOR_INTERRUPTS, CheckDeadLock(), CheckRecoveryConflictDeadlock(), 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, 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 1706 of file proc.c.

1707{
1708 if (dlist_node_is_detached(&proc->waitLink))
1709 return;
1710
1712
1713 /* Remove process from wait queue */
1715
1716 /* Clean up process' state and pass it the ok/fail signal */
1717 proc->waitLock = NULL;
1718 proc->waitProcLock = NULL;
1719 proc->waitStatus = waitStatus;
1720 pg_atomic_write_u64(&proc->waitStart, 0);
1721
1722 /* And awaken it */
1723 SetLatch(&proc->procLatch);
1724}
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(), pg_atomic_write_u64(), PROC_WAIT_STATUS_WAITING, PGPROC::procLatch, SetLatch(), PGPROC::waitLink, 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 901 of file proc.c.

902{
903 Assert(MyProc != NULL);
905}
void ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
Definition procarray.c:569

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

Referenced by InitProcessPhase2().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 747 of file proc.c.

748{
749 /* use volatile pointer to prevent code rearrangement */
750 volatile PROC_HDR *procglobal = ProcGlobal;
751
753}

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

Referenced by LockBufferForCleanup().

Variable Documentation

◆ AuxiliaryProcs

NON_EXEC_STATIC PGPROC* AuxiliaryProcs = NULL

◆ DeadlockTimeout

◆ got_deadlock_timeout

volatile sig_atomic_t got_deadlock_timeout
static

Definition at line 76 of file proc.c.

Referenced by CheckDeadLockAlert(), and ProcSleep().

◆ IdleInTransactionSessionTimeout

int IdleInTransactionSessionTimeout = 0

Definition at line 62 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

int IdleSessionTimeout = 0

Definition at line 64 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

int LockTimeout = 0

Definition at line 61 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

bool log_lock_waits = true

Definition at line 65 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGPROC* MyProc = NULL

Definition at line 68 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(), HandleRecoveryConflictInterrupt(), 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(), MarkSharedBufferDirtyHint(), 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(), ProcessInterrupts(), ProcessRecoveryConflictInterrupts(), ProcessStandbyHSFeedbackMessage(), ProcKill(), ProcReleaseLocks(), ProcSleep(), RecordTransactionCommit(), RecordTransactionCommitPrepared(), ReinitializeParallelDSM(), RelationTruncate(), RemoveProcFromArray(), ReplicationSlotRelease(), report_recovery_conflict(), 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 73 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ StatementTimeout

int StatementTimeout = 0

Definition at line 60 of file proc.c.

Referenced by enable_statement_timeout().

◆ TransactionTimeout