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/clog.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 "storage/subsystems.h"
#include "utils/injection_point.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 ProcGlobalShmemRequest (void *arg)
 
static void ProcGlobalShmemInit (void *arg)
 
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 CalculateFastPathLockShmemSize (void)
 
int ProcGlobalSemas (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
 
static voidAllProcsShmemPtr
 
static voidFastPathLockArrayShmemPtr
 
NON_EXEC_STATIC PGPROCAuxiliaryProcs = NULL
 
PGPROCPreparedXactProcs = NULL
 
const ShmemCallbacks ProcGlobalShmemCallbacks
 
static uint32 TotalProcs
 
static size_t ProcGlobalAllProcsShmemSize
 
static size_t FastPathLockArrayShmemSize
 
static volatile sig_atomic_t got_deadlock_timeout
 

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC * AuxiliaryPidGetProc ( int  pid)

Definition at line 1097 of file proc.c.

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

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

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

1047{
1048 int proctype = DatumGetInt32(arg);
1050 PGPROC *proc;
1051
1053
1054 /* not safe if forked by system(), etc. */
1055 if (MyProc->pid != (int) getpid())
1056 elog(PANIC, "AuxiliaryProcKill() called in child process");
1057
1059
1060 Assert(MyProc == auxproc);
1061
1062 /* Release any LW locks I am holding (see notes above) */
1064
1065 /* Cancel any pending condition variable sleep, too */
1067
1068 /* look at the equivalent ProcKill() code for comments */
1071
1072 proc = MyProc;
1073 MyProc = NULL;
1075 DisownLatch(&proc->procLatch);
1076
1078
1079 /* Mark auxiliary proc no longer in use */
1080 proc->pid = 0;
1083
1084 /* Update shared estimate of spins_per_delay */
1086
1088}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
#define Assert(condition)
Definition c.h:943
bool ConditionVariableCancelSleep(void)
Datum arg
Definition elog.c:1322
#define PANIC
Definition elog.h:44
#define elog(elevel,...)
Definition elog.h:228
ProcNumber MyProcNumber
Definition globals.c:92
void DisownLatch(Latch *latch)
Definition latch.c:144
void LWLockReleaseAll(void)
Definition lwlock.c:1866
void SwitchBackToLocalLatch(void)
Definition miscinit.c:243
static int32 DatumGetInt32(Datum X)
Definition postgres.h:202
#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:71
PROC_HDR * ProcGlobal
Definition proc.c:74
LocalTransactionId lxid
Definition proc.h:231
ProcNumber procNumber
Definition proc.h:226
struct PGPROC::@136 vxid
Latch procLatch
Definition proc.h:256
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:347

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

2043{
2045
2046 /* If we already did it, we don't need to do it again. */
2048 return;
2049
2050 /* We had better not be a follower. */
2052
2053 /* Create single-member group, containing only ourselves. */
2059}
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition ilist.h:347
#define LockHashPartitionLockByProc(leader_pgproc)
Definition lock.h:372
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_EXCLUSIVE
Definition lwlock.h:104
dlist_head lockGroupMembers
Definition proc.h:299
dlist_node lockGroupLink
Definition proc.h:300
PGPROC * lockGroupLeader
Definition proc.h:298

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

Referenced by LaunchParallelWorkers(), and rebuild_relation().

◆ BecomeLockGroupMember()

bool BecomeLockGroupMember ( PGPROC leader,
int  pid 
)

Definition at line 2072 of file proc.c.

2073{
2075 bool ok = false;
2076
2077 /* Group leader can't become member of group */
2078 Assert(MyProc != leader);
2079
2080 /* Can't already be a member of a group */
2082
2083 /* PID must be valid. */
2084 Assert(pid != 0);
2085
2086 /*
2087 * Get lock protecting the group fields. Note LockHashPartitionLockByProc
2088 * calculates the proc number based on the PGPROC slot without looking at
2089 * its contents, so we will acquire the correct lock even if the leader
2090 * PGPROC is in process of being recycled.
2091 */
2094
2095 /* Is this the leader we're looking for? */
2096 if (leader->pid == pid && leader->lockGroupLeader == leader)
2097 {
2098 /* OK, join the group */
2099 ok = true;
2100 MyProc->lockGroupLeader = leader;
2102 }
2104
2105 return ok;
2106}
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(), and RepackWorkerMain().

◆ CalculateFastPathLockShmemSize()

static Size CalculateFastPathLockShmemSize ( void  )
static

Definition at line 105 of file proc.c.

106{
107 Size size = 0;
110
111 /*
112 * Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are
113 * nicely aligned in each backend.
114 */
117
119
120 Assert(TotalProcs > 0);
121 Assert(size > 0);
122
123 return size;
124}
#define MAXALIGN(LEN)
Definition c.h:896
uint64_t uint64
Definition c.h:625
size_t Size
Definition c.h:689
int FastPathLockGroupsPerBackend
Definition lock.c:205
unsigned int Oid
#define FastPathLockSlotsPerBackend()
Definition proc.h:97
Size add_size(Size s1, Size s2)
Definition shmem.c:1048
Size mul_size(Size s1, Size s2)
Definition shmem.c:1063
static uint32 TotalProcs
Definition proc.c:88

References add_size(), Assert, FastPathLockGroupsPerBackend, FastPathLockSlotsPerBackend, fb(), MAXALIGN, mul_size(), and TotalProcs.

Referenced by ProcGlobalShmemRequest().

◆ CheckDeadLock()

static DeadLockState CheckDeadLock ( void  )
static

Definition at line 1823 of file proc.c.

1824{
1825 int i;
1827
1828 /*
1829 * Acquire exclusive lock on the entire shared lock data structures. Must
1830 * grab LWLocks in partition-number order to avoid LWLock deadlock.
1831 *
1832 * Note that the deadlock check interrupt had better not be enabled
1833 * anywhere that this process itself holds lock partition locks, else this
1834 * will wait forever. Also note that LWLockAcquire creates a critical
1835 * section, so that this routine cannot be interrupted by cancel/die
1836 * interrupts.
1837 */
1838 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
1840
1841 /*
1842 * Check to see if we've been awoken by anyone in the interim.
1843 *
1844 * If we have, we can return and resume our transaction -- happy day.
1845 * Before we are awoken the process releasing the lock grants it to us so
1846 * we know that we don't have to wait anymore.
1847 *
1848 * We check by looking to see if we've been unlinked from the wait queue.
1849 * This is safe because we hold the lock partition lock.
1850 */
1852 {
1854 goto check_done;
1855 }
1856
1857#ifdef LOCK_DEBUG
1858 if (Debug_deadlocks)
1859 DumpAllLocks();
1860#endif
1861
1862 /* Run the deadlock check */
1864
1865 if (result == DS_HARD_DEADLOCK)
1866 {
1867 /*
1868 * Oops. We have a deadlock.
1869 *
1870 * Get this process out of wait state. (Note: we could do this more
1871 * efficiently by relying on lockAwaited, but use this coding to
1872 * preserve the flexibility to kill some other transaction than the
1873 * one detecting the deadlock.)
1874 *
1875 * RemoveFromWaitQueue sets MyProc->waitStatus to
1876 * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
1877 * return.
1878 */
1881
1882 /*
1883 * We're done here. Transaction abort caused by the error that
1884 * ProcSleep will raise will cause any other locks we hold to be
1885 * released, thus allowing other processes to wake up; we don't need
1886 * to do that here. NOTE: an exception is that releasing locks we
1887 * hold doesn't consider the possibility of waiters that were blocked
1888 * behind us on the lock we just failed to get, and might now be
1889 * wakable because we're not in front of them anymore. However,
1890 * RemoveFromWaitQueue took care of waking up any such processes.
1891 */
1892 }
1893
1894 /*
1895 * And release locks. We do this in reverse order for two reasons: (1)
1896 * Anyone else who needs more than one of the locks will be trying to lock
1897 * them in increasing order; we don't want to release the other process
1898 * until it can get all the locks it needs. (2) This avoids O(N^2)
1899 * behavior inside LWLockRelease.
1900 */
1902 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
1904
1905 return result;
1906}
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:2055
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:555
DeadLockState
Definition lock.h:340
@ DS_HARD_DEADLOCK
Definition lock.h:344
@ DS_NO_DEADLOCK
Definition lock.h:342
#define LockHashPartitionLockByIndex(i)
Definition lock.h:360
#define NUM_LOCK_PARTITIONS
Definition lwlock.h:87
LOCKTAG tag
Definition lock.h:142
LOCK * waitLock
Definition proc.h:304
dlist_node waitLink
Definition proc.h:305

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(), result, LOCK::tag, PGPROC::waitLink, and PGPROC::waitLock.

Referenced by ProcSleep().

◆ CheckDeadLockAlert()

void CheckDeadLockAlert ( void  )

Definition at line 1914 of file proc.c.

1915{
1916 int save_errno = errno;
1917
1918 got_deadlock_timeout = true;
1919
1920 /*
1921 * Have to set the latch again, even if handle_sig_alarm already did. Back
1922 * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1923 * ever would be a problem, but setting a set latch again is cheap.
1924 *
1925 * Note that, when this function runs inside procsignal_sigusr1_handler(),
1926 * the handler function sets the latch again after the latch is set here.
1927 */
1929 errno = save_errno;
1930}
struct Latch * MyLatch
Definition globals.c:65
void SetLatch(Latch *latch)
Definition latch.c:290
static volatile sig_atomic_t got_deadlock_timeout
Definition proc.c:93

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

Referenced by InitPostgres(), and ProcessRecoveryConflictInterrupt().

◆ GetLockHoldersAndWaiters()

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

Definition at line 1941 of file proc.c.

1943{
1946 LOCK *lock = locallock->lock;
1947 bool first_holder = true,
1948 first_waiter = true;
1949
1950#ifdef USE_ASSERT_CHECKING
1951 {
1952 uint32 hashcode = locallock->hashcode;
1954
1956 }
1957#endif
1958
1959 *lockHoldersNum = 0;
1960
1961 /*
1962 * Loop over the lock's procLocks to gather a list of all holders and
1963 * waiters. Thus we will be able to provide more detailed information for
1964 * lock debugging purposes.
1965 *
1966 * lock->procLocks contains all processes which hold or wait for this
1967 * lock.
1968 */
1970 {
1971 curproclock =
1972 dlist_container(PROCLOCK, lockLink, proc_iter.cur);
1973
1974 /*
1975 * We are a waiter if myProc->waitProcLock == curproclock; we are a
1976 * holder if it is NULL or something different.
1977 */
1978 if (curproclock->tag.myProc->waitProcLock == curproclock)
1979 {
1980 if (first_waiter)
1981 {
1983 curproclock->tag.myProc->pid);
1984 first_waiter = false;
1985 }
1986 else
1988 curproclock->tag.myProc->pid);
1989 }
1990 else
1991 {
1992 if (first_holder)
1993 {
1995 curproclock->tag.myProc->pid);
1996 first_holder = false;
1997 }
1998 else
2000 curproclock->tag.myProc->pid);
2001
2002 (*lockHoldersNum)++;
2003 }
2004 }
2005}
uint32_t uint32
Definition c.h:624
#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:357
bool LWLockHeldByMe(LWLock *lock)
Definition lwlock.c:1885
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
Definition lock.h:140
dlist_head procLocks
Definition lock.h:147

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

772{
773 /* use volatile pointer to prevent code rearrangement */
774 volatile PROC_HDR *procglobal = ProcGlobal;
775
777}
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 787 of file proc.c.

788{
789 dlist_iter iter;
790
791 Assert(n > 0);
792 Assert(nfree);
793
795
796 *nfree = 0;
798 {
799 (*nfree)++;
800 if (*nfree == n)
801 break;
802 }
803
805
806 return (*nfree == n);
807}
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 618 of file proc.c.

619{
621 int proctype;
622
623 /*
624 * ProcGlobal should be set up already (if we are a backend, we inherit
625 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
626 */
627 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
628 elog(PANIC, "proc header uninitialized");
629
630 if (MyProc != NULL)
631 elog(ERROR, "you already exist");
632
635
636 /*
637 * We use the freeProcsLock to protect assignment and releasing of
638 * AuxiliaryProcs entries.
639 *
640 * While we are holding the spinlock, also copy the current shared
641 * estimate of spins_per_delay to local storage.
642 */
644
646
647 /*
648 * Find a free auxproc ... *big* trouble if there isn't one ...
649 */
651 {
653 if (auxproc->pid == 0)
654 break;
655 }
657 {
659 elog(FATAL, "all AuxiliaryProcs are in use");
660 }
661
662 /* Mark auxiliary proc as in use by me */
663 /* use volatile pointer to prevent code rearrangement */
664 ((volatile PGPROC *) auxproc)->pid = MyProcPid;
665
667
668 MyProc = auxproc;
670
671 /*
672 * Initialize all fields of MyProc, except for those previously
673 * initialized by ProcGlobalShmemInit.
674 */
677 MyProc->fpVXIDLock = false;
688 MyProc->statusFlags = 0;
690 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
705
706 /*
707 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
708 * on it. That allows us to repoint the process latch, which so far
709 * points to process local one, to the shared one.
710 */
713
714 /* now that we have a proc, report wait events to shared memory */
716
717 /* Check that group locking fields are in a proper initial state. */
720
721 /*
722 * We might be reusing a semaphore that belonged to a failed process. So
723 * be careful and reinitialize its value here. (This is not strictly
724 * necessary anymore, but seems like a good idea for cleanliness.)
725 */
727
728 /*
729 * Arrange to clean up at process exit.
730 */
732
733 /*
734 * Now that we have a PGPROC, we could try to acquire lightweight locks.
735 * Initialize local state needed for them. (Heavyweight locks cannot be
736 * acquired in aux processes.)
737 */
739
740#ifdef EXEC_BACKEND
741
742 /*
743 * Initialize backend-local pointers to all the shared data structures.
744 * (We couldn't do this until now because it needs LWLocks.)
745 */
748#endif
749}
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:42
#define ERROR
Definition elog.h:40
int MyProcPid
Definition globals.c:49
bool IsUnderPostmaster
Definition globals.c:122
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:68
void InitLWLockAccess(void)
Definition lwlock.c:506
@ 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:289
void PGSemaphoreReset(PGSemaphore sema)
Definition posix_sema.c:288
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
#define InvalidOid
#define GetNumberFromPGProc(proc)
Definition proc.h:505
@ PROC_WAIT_STATUS_OK
Definition proc.h:145
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:1046
TransactionId xmin
Definition proc.h:242
PROCLOCK * waitProcLock
Definition proc.h:306
dlist_node freeProcsLink
Definition proc.h:186
uint8 lwWaitMode
Definition proc.h:284
uint32 wait_event_info
Definition proc.h:378
BackendType backendType
Definition proc.h:198
uint8 statusFlags
Definition proc.h:210
Oid databaseId
Definition proc.h:201
pg_atomic_uint64 waitStart
Definition proc.h:311
bool fpVXIDLock
Definition proc.h:327
TransactionId xid
Definition proc.h:237
int delayChkptFlags
Definition proc.h:260
pg_atomic_uint32 pendingRecoveryConflicts
Definition proc.h:270
LocalTransactionId fpLocalTransactionId
Definition proc.h:328
PGSemaphore sem
Definition proc.h:258
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition proc.h:321
Oid roleId
Definition proc.h:202
ProcWaitStatus waitStatus
Definition proc.h:314
Oid tempNamespaceId
Definition proc.h:204
uint8 lwWaiting
Definition proc.h:283
void pgstat_set_wait_event_storage(uint32 *wait_event_info)
Definition wait_event.c:335

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

393{
394 dlist_head *procgloballist;
395
396 /*
397 * ProcGlobal should be set up already (if we are a backend, we inherit
398 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
399 */
400 if (ProcGlobal == NULL)
401 elog(PANIC, "proc header uninitialized");
402
403 if (MyProc != NULL)
404 elog(ERROR, "you already exist");
405
406 /*
407 * Before we start accessing the shared memory in a serious way, mark
408 * ourselves as an active postmaster child; this is so that the postmaster
409 * can detect it if we exit without cleaning up.
410 */
413
414 /*
415 * Decide which list should supply our PGPROC. This logic must match the
416 * way the freelists were constructed in ProcGlobalShmemInit().
417 */
419 procgloballist = &ProcGlobal->autovacFreeProcs;
420 else if (AmBackgroundWorkerProcess())
421 procgloballist = &ProcGlobal->bgworkerFreeProcs;
422 else if (AmWalSenderProcess())
423 procgloballist = &ProcGlobal->walsenderFreeProcs;
424 else
425 procgloballist = &ProcGlobal->freeProcs;
426
427 /*
428 * Try to get a proc struct from the appropriate free list. If this
429 * fails, we must be out of PGPROC structures (not to mention semaphores).
430 *
431 * While we are holding the spinlock, also copy the current shared
432 * estimate of spins_per_delay to local storage.
433 */
435
437
438 if (!dlist_is_empty(procgloballist))
439 {
440 MyProc = dlist_container(PGPROC, freeProcsLink, dlist_pop_head_node(procgloballist));
442 }
443 else
444 {
445 /*
446 * If we reach here, all the PGPROCs are in use. This is one of the
447 * possible places to detect "too many backends", so give the standard
448 * error message. XXX do we need to give a different failure message
449 * in the autovacuum case?
450 */
452 if (AmWalSenderProcess())
455 errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
459 errmsg("sorry, too many clients already")));
460 }
462
463 /*
464 * Cross-check that the PGPROC is of the type we expect; if this were not
465 * the case, it would get returned to the wrong list.
466 */
467 Assert(MyProc->procgloballist == procgloballist);
468
469 /*
470 * Initialize all fields of MyProc, except for those previously
471 * initialized by ProcGlobalShmemInit.
472 */
475 MyProc->fpVXIDLock = false;
482 /* databaseId and roleId will be filled in later */
488 MyProc->statusFlags = 0;
489 /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
493 MyProc->lwWaitMode = 0;
498#ifdef USE_ASSERT_CHECKING
499 {
500 int i;
501
502 /* Last process should have released all locks. */
503 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
505 }
506#endif
508
509 /* Initialize fields for sync rep */
513
514 /* Initialize fields for group XID clearing. */
518
519 /* Check that group locking fields are in a proper initial state. */
522
523 /* Initialize wait event information. */
525
526 /* Initialize fields for group transaction status update. */
527 MyProc->clogGroupMember = false;
533
534 /*
535 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
536 * on it. That allows us to repoint the process latch, which so far
537 * points to process local one, to the shared one.
538 */
541
542 /* now that we have a proc, report wait events to shared memory */
544
545 /*
546 * We might be reusing a semaphore that belonged to a failed process. So
547 * be careful and reinitialize its value here. (This is not strictly
548 * necessary anymore, but seems like a good idea for cleanliness.)
549 */
551
552 /*
553 * Arrange to clean up at backend exit.
554 */
556
557 /*
558 * Now that we have a PGPROC, we could try to acquire locks, so initialize
559 * local state needed for LWLocks, and the deadlock checker.
560 */
563
564#ifdef EXEC_BACKEND
565
566 /*
567 * Initialize backend-local pointers to all the shared data structures.
568 * (We couldn't do this until now because it needs LWLocks.)
569 */
572#endif
573}
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:152
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition ilist.h:450
#define AmAutoVacuumWorkerProcess()
Definition miscadmin.h:398
#define AmBackgroundWorkerProcess()
Definition miscadmin.h:399
#define AmWalSenderProcess()
Definition miscadmin.h:400
#define AmSpecialWorkerProcess()
Definition miscadmin.h:414
static char * errmsg
#define PROC_IS_AUTOVACUUM
Definition proc.h:61
static void ProcKill(int code, Datum arg)
Definition proc.c:924
bool procArrayGroupMember
Definition proc.h:350
XLogRecPtr clogGroupMemberLsn
Definition proc.h:371
pg_atomic_uint32 procArrayGroupNext
Definition proc.h:352
dlist_head * procgloballist
Definition proc.h:185
TransactionId clogGroupMemberXid
Definition proc.h:366
int64 clogGroupMemberPage
Definition proc.h:369
bool clogGroupMember
Definition proc.h:364
XLogRecPtr waitLSN
Definition proc.h:341
dlist_node syncRepLinks
Definition proc.h:343
int syncRepState
Definition proc.h:342
pg_atomic_uint32 clogGroupNext
Definition proc.h:365
XidStatus clogGroupMemberXidStatus
Definition proc.h:367
TransactionId procArrayGroupMemberXid
Definition proc.h:358
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:141
#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 583 of file proc.c.

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

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

Referenced by InitPostgres().

◆ JoinWaitQueue()

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

Definition at line 1146 of file proc.c.

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

819{
823
825
827
828 /* Nothing to do if we weren't waiting for a lock */
830 if (lockAwaited == NULL)
831 {
833 return;
834 }
835
836 /*
837 * Turn off the deadlock and lock timeout timers, if they are still
838 * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
839 * indicator flag, since this function is executed before
840 * ProcessInterrupts when responding to SIGINT; else we'd lose the
841 * knowledge that the SIGINT came from a lock timeout and not an external
842 * source.
843 */
845 timeouts[0].keep_indicator = false;
846 timeouts[1].id = LOCK_TIMEOUT;
847 timeouts[1].keep_indicator = true;
849
850 /* Unlink myself from the wait queue, if on it (might not be anymore!) */
853
855 {
856 /* We could not have been granted the lock yet */
858 }
859 else
860 {
861 /*
862 * Somebody kicked us off the lock queue already. Perhaps they
863 * granted us the lock, or perhaps they detected a deadlock. If they
864 * did grant us the lock, we'd better remember it in our local lock
865 * table.
866 */
869 }
870
872
874
876}
void GrantAwaitedLock(void)
Definition lock.c:1898
void ResetAwaitedLock(void)
Definition lock.c:1916
void AbortStrongLockAcquire(void)
Definition lock.c:1869
LOCALLOCK * GetAwaitedLock(void)
Definition lock.c:1907
#define RESUME_INTERRUPTS()
Definition miscadmin.h:138
#define HOLD_INTERRUPTS()
Definition miscadmin.h:136
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().

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 130 of file proc.c.

131{
132 /*
133 * We need a sema per backend (including autovacuum), plus one for each
134 * auxiliary process.
135 */
137}
int MaxBackends
Definition globals.c:149

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by InitializeShmemGUCs(), ProcGlobalShmemInit(), and ProcGlobalShmemRequest().

◆ ProcGlobalShmemInit()

static void ProcGlobalShmemInit ( void arg)
static

Definition at line 221 of file proc.c.

222{
223 char *ptr;
224 size_t requestSize;
225 PGPROC *procs;
226 int i,
227 j;
228
229 /* Used for setup of per-backend fast-path slots. */
230 char *fpPtr,
234
247
248 ptr = AllProcsShmemPtr;
250 MemSet(ptr, 0, requestSize);
251
252 /* Carve out the allProcs array from the shared memory area */
253 procs = (PGPROC *) ptr;
254 ptr = ptr + TotalProcs * sizeof(PGPROC);
255
256 ProcGlobal->allProcs = procs;
257 /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
259
260 /*
261 * Carve out arrays mirroring PGPROC fields in a dense manner. See
262 * PROC_HDR.
263 *
264 * XXX: It might make sense to increase padding for these arrays, given
265 * how hotly they are accessed.
266 */
267 ProcGlobal->xids = (TransactionId *) ptr;
268 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
269
271 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
272
273 ProcGlobal->statusFlags = (uint8 *) ptr;
274 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
275
276 /* make sure we didn't overflow */
277 Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
278
279 /*
280 * Initialize arrays for fast-path locks. Those are variable-length, so
281 * can't be included in PGPROC directly. We allocate a separate piece of
282 * shared memory and then divide that between backends.
283 */
286
290
291 /* For asserts checking we did not overflow. */
293
294 /* Initialize semaphores */
296
297 for (i = 0; i < TotalProcs; i++)
298 {
299 PGPROC *proc = &procs[i];
300
301 /* Common initialization for all PGPROCs, regardless of type. */
302
303 /*
304 * Set the fast-path lock arrays, and move the pointer. We interleave
305 * the two arrays, to (hopefully) get some locality for each backend.
306 */
307 proc->fpLockBits = (uint64 *) fpPtr;
309
310 proc->fpRelId = (Oid *) fpPtr;
312
314
315 /*
316 * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
317 * dummy PGPROCs don't need these though - they're never associated
318 * with a real process
319 */
321 {
322 proc->sem = PGSemaphoreCreate();
323 InitSharedLatch(&(proc->procLatch));
325 }
326
327 /*
328 * Newly created PGPROCs for normal backends, autovacuum workers,
329 * special workers, bgworkers, and walsenders must be queued up on the
330 * appropriate free list. Because there can only ever be a small,
331 * fixed number of auxiliary processes, no free list is used in that
332 * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs
333 * for prepared transactions are added to a free list by
334 * TwoPhaseShmemInit().
335 */
336 if (i < MaxConnections)
337 {
338 /* PGPROC for normal backend, add to freeProcs list */
341 }
343 {
344 /* PGPROC for AV or special worker, add to autovacFreeProcs list */
347 }
349 {
350 /* PGPROC for bgworker, add to bgworkerFreeProcs list */
353 }
354 else if (i < MaxBackends)
355 {
356 /* PGPROC for walsender, add to walsenderFreeProcs list */
359 }
360
361 /* Initialize myProcLocks[] shared memory queues. */
362 for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
363 dlist_init(&(proc->myProcLocks[j]));
364
365 /* Initialize lockGroupMembers list. */
367
368 /*
369 * Initialize the atomic variables, otherwise, it won't be safe to
370 * access them for backends that aren't currently in use.
371 */
374 pg_atomic_init_u64(&(proc->waitStart), 0);
375 }
376
377 /* Should have consumed exactly the expected amount of fast-path memory. */
379
380 /*
381 * Save pointers to the blocks of PGPROC structures reserved for auxiliary
382 * processes and prepared transactions.
383 */
384 AuxiliaryProcs = &procs[MaxBackends];
386}
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:124
uint8_t uint8
Definition c.h:622
#define MemSet(start, val, len)
Definition c.h:1107
uint32 TransactionId
Definition c.h:736
int MaxConnections
Definition globals.c:145
int max_worker_processes
Definition globals.c:146
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:670
void PGSemaphoreInit(int maxSemas)
Definition posix_sema.c:198
PGSemaphore PGSemaphoreCreate(void)
Definition posix_sema.c:255
#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
static void SpinLockInit(volatile slock_t *lock)
Definition spin.h:50
PGPROC * PreparedXactProcs
Definition proc.c:78
static void * FastPathLockArrayShmemPtr
Definition proc.c:76
static void * AllProcsShmemPtr
Definition proc.c:75
int ProcGlobalSemas(void)
Definition proc.c:130
static size_t ProcGlobalAllProcsShmemSize
Definition proc.c:89
static size_t FastPathLockArrayShmemSize
Definition proc.c:90
LWLock fpInfoLock
Definition proc.h:324
Oid * fpRelId
Definition proc.h:326
uint64 * fpLockBits
Definition proc.h:325
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, AllProcsShmemPtr, 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(), FastPathLockArrayShmemPtr, FastPathLockArrayShmemSize, FastPathLockGroupsPerBackend, 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_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, PGSemaphoreCreate(), PGSemaphoreInit(), PreparedXactProcs, PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupNext, ProcGlobal, ProcGlobalAllProcsShmemSize, PGPROC::procgloballist, ProcGlobalSemas(), PGPROC::procLatch, PGPROC::sem, SpinLockInit(), PROC_HDR::spins_per_delay, PROC_HDR::startupBufferPinWaitBufId, PROC_HDR::statusFlags, PROC_HDR::subxidStates, TotalProcs, PGPROC::waitStart, PROC_HDR::walsenderFreeProcs, PROC_HDR::walwriterProc, and PROC_HDR::xids.

◆ ProcGlobalShmemRequest()

static void ProcGlobalShmemRequest ( void arg)
static

Definition at line 147 of file proc.c.

148{
149 Size size;
150
151 /*
152 * Reserve all the PGPROC structures we'll need. There are six separate
153 * consumers: (1) normal backends, (2) autovacuum workers and special
154 * workers, (3) background workers, (4) walsenders, (5) auxiliary
155 * processes, and (6) prepared transactions. (For largely-historical
156 * reasons, we combine autovacuum and special workers into one category
157 * with a single freelist.) Each PGPROC structure is dedicated to exactly
158 * one of these purposes, and they do not move between groups.
159 */
160 TotalProcs =
162
163 size = 0;
164 size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
165 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
166 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
167 size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
169 ShmemRequestStruct(.name = "PGPROC structures",
171 .ptr = &AllProcsShmemPtr,
172 );
173
176 else
178 ShmemRequestStruct(.name = "Fast-Path Lock Array",
179 .size = size,
181 );
182
183 /*
184 * ProcGlobal is registered here in .ptr as usual, but it needs to be
185 * propagated specially in EXEC_BACKEND mode, because ProcGlobal needs to
186 * be accessed early at backend startup, before ShmemAttachRequested() has
187 * been called.
188 */
189 ShmemRequestStruct(.name = "Proc Header",
190 .size = sizeof(PROC_HDR),
191 .ptr = (void **) &ProcGlobal,
192 );
193
194 /* Let the semaphore implementation register its shared memory needs */
196}
void PGSemaphoreShmemRequest(int maxSemas)
Definition posix_sema.c:165
#define SHMEM_ATTACH_UNKNOWN_SIZE
Definition shmem.h:69
#define ShmemRequestStruct(...)
Definition shmem.h:176
static Size CalculateFastPathLockShmemSize(void)
Definition proc.c:105
int max_prepared_xacts
Definition twophase.c:118
const char * name

References add_size(), AllProcsShmemPtr, CalculateFastPathLockShmemSize(), FastPathLockArrayShmemPtr, FastPathLockArrayShmemSize, IsUnderPostmaster, max_prepared_xacts, MaxBackends, mul_size(), name, NUM_AUXILIARY_PROCS, PGSemaphoreShmemRequest(), ProcGlobal, ProcGlobalAllProcsShmemSize, ProcGlobalSemas(), SHMEM_ATTACH_UNKNOWN_SIZE, ShmemRequestStruct, PROC_HDR::statusFlags, PROC_HDR::subxidStates, TotalProcs, and PROC_HDR::xids.

◆ ProcKill()

static void ProcKill ( int  code,
Datum  arg 
)
static

Definition at line 924 of file proc.c.

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

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

1777{
1781
1783 return;
1784
1786 {
1787 PGPROC *proc = dlist_container(PGPROC, waitLink, miter.cur);
1788 LOCKMODE lockmode = proc->waitLockMode;
1789
1790 /*
1791 * Waken if (a) doesn't conflict with requests of earlier waiters, and
1792 * (b) doesn't conflict with already-held locks.
1793 */
1794 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1795 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1796 proc->waitProcLock))
1797 {
1798 /* OK to waken */
1799 GrantLock(lock, proc->waitProcLock, lockmode);
1800 /* removes proc from the lock's waiting process queue */
1802 }
1803 else
1804 {
1805 /*
1806 * Lock conflicts: Don't wake, but remember requested mode for
1807 * later checks.
1808 */
1809 aheadRequests |= LOCKBIT_ON(lockmode);
1810 }
1811 }
1812}
#define dclist_foreach_modify(iter, lhead)
Definition ilist.h:973
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition proc.c:1748

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

897{
898 if (!MyProc)
899 return;
900 /* If waiting, get off wait queue (should only be needed after error) */
902 /* Release standard locks, including session-level if aborting */
904 /* Release transaction-level advisory locks */
906}
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition lock.c:2316
#define DEFAULT_LOCKMETHOD
Definition locktag.h:25
#define USER_LOCKMETHOD
Definition locktag.h:26
void LockErrorCleanup(void)
Definition proc.c:818

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 2027 of file proc.c.

2028{
2030 elog(ERROR, "procNumber out of range");
2031
2032 SetLatch(&GetPGProcByNumber(procNumber)->procLatch);
2033}
#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 1315 of file proc.c.

1316{
1317 LOCKMODE lockmode = locallock->tag.mode;
1318 LOCK *lock = locallock->lock;
1319 uint32 hashcode = locallock->hashcode;
1322 bool allow_autovacuum_cancel = true;
1323 bool logged_recovery_conflict = false;
1324 bool logged_lock_wait = false;
1327
1328 /* The caller must've armed the on-error cleanup mechanism */
1331
1332 /*
1333 * Now that we will successfully clean up after an ereport, it's safe to
1334 * check to see if there's a buffer pin deadlock against the Startup
1335 * process. Of course, that's only necessary if we're doing Hot Standby
1336 * and are not the Startup process ourselves.
1337 */
1340
1341 /* Reset deadlock_state before enabling the timeout handler */
1343 got_deadlock_timeout = false;
1344
1345 /*
1346 * Set timer so we can wake up after awhile and check for a deadlock. If a
1347 * deadlock is detected, the handler sets MyProc->waitStatus =
1348 * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
1349 * rather than success.
1350 *
1351 * By delaying the check until we've waited for a bit, we can avoid
1352 * running the rather expensive deadlock-check code in most cases.
1353 *
1354 * If LockTimeout is set, also enable the timeout for that. We can save a
1355 * few cycles by enabling both timeout sources in one call.
1356 *
1357 * If InHotStandby we set lock waits slightly later for clarity with other
1358 * code.
1359 */
1360 if (!InHotStandby)
1361 {
1362 if (LockTimeout > 0)
1363 {
1365
1367 timeouts[0].type = TMPARAM_AFTER;
1368 timeouts[0].delay_ms = DeadlockTimeout;
1369 timeouts[1].id = LOCK_TIMEOUT;
1370 timeouts[1].type = TMPARAM_AFTER;
1371 timeouts[1].delay_ms = LockTimeout;
1373 }
1374 else
1376
1377 /*
1378 * Use the current time obtained for the deadlock timeout timer as
1379 * waitStart (i.e., the time when this process started waiting for the
1380 * lock). Since getting the current time newly can cause overhead, we
1381 * reuse the already-obtained time to avoid that overhead.
1382 *
1383 * Note that waitStart is updated without holding the lock table's
1384 * partition lock, to avoid the overhead by additional lock
1385 * acquisition. This can cause "waitstart" in pg_locks to become NULL
1386 * for a very short period of time after the wait started even though
1387 * "granted" is false. This is OK in practice because we can assume
1388 * that users are likely to look at "waitstart" when waiting for the
1389 * lock for a long time.
1390 */
1393 }
1395 {
1396 /*
1397 * Set the wait start timestamp if logging is enabled and in hot
1398 * standby.
1399 */
1401 }
1402
1403 /*
1404 * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1405 * will not wait. But a set latch does not necessarily mean that the lock
1406 * is free now, as there are many other sources for latch sets than
1407 * somebody releasing the lock.
1408 *
1409 * We process interrupts whenever the latch has been set, so cancel/die
1410 * interrupts are processed quickly. This means we must not mind losing
1411 * control to a cancel/die interrupt here. We don't, because we have no
1412 * shared-state-change work to do after being granted the lock (the
1413 * grantor did it all). We do have to worry about canceling the deadlock
1414 * timeout and updating the locallock table, but if we lose control to an
1415 * error, LockErrorCleanup will fix that up.
1416 */
1417 do
1418 {
1419 if (InHotStandby)
1420 {
1421 bool maybe_log_conflict =
1423
1424 /* Set a timer and wait for that or for the lock to be granted */
1427
1428 /*
1429 * Emit the log message if the startup process is waiting longer
1430 * than deadlock_timeout for recovery conflict on lock.
1431 */
1433 {
1435
1438 {
1440 int cnt;
1441
1442 vxids = GetLockConflicts(&locallock->tag.lock,
1443 AccessExclusiveLock, &cnt);
1444
1445 /*
1446 * Log the recovery conflict and the list of PIDs of
1447 * backends holding the conflicting lock. Note that we do
1448 * logging even if there are no such backends right now
1449 * because the startup process here has already waited
1450 * longer than deadlock_timeout.
1451 */
1454 cnt > 0 ? vxids : NULL, true);
1456 }
1457 }
1458 }
1459 else
1460 {
1462 PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1464 /* check for deadlocks first, as that's probably log-worthy */
1466 {
1468 got_deadlock_timeout = false;
1469 }
1471 }
1472
1473 /*
1474 * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
1475 * else asynchronously. Read it just once per loop to prevent
1476 * surprising behavior (such as missing log messages).
1477 */
1478 myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
1479
1480 /*
1481 * If we are not deadlocked, but are waiting on an autovacuum-induced
1482 * task, send a signal to interrupt it.
1483 */
1485 {
1487 uint8 statusFlags;
1490
1491 /*
1492 * Grab info we need, then release lock immediately. Note this
1493 * coding means that there is a tiny chance that the process
1494 * terminates its current transaction and starts a different one
1495 * before we have a change to send the signal; the worst possible
1496 * consequence is that a for-wraparound vacuum is canceled. But
1497 * that could happen in any case unless we were to do kill() with
1498 * the lock held, which is much more undesirable.
1499 */
1501 statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1503 locktag_copy = lock->tag;
1505
1506 /*
1507 * Only do it if the worker is not working to protect against Xid
1508 * wraparound.
1509 */
1510 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
1511 !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
1512 {
1513 int pid = autovac->pid;
1514
1515 /* report the case, if configured to do so */
1517 {
1519 StringInfoData logbuf; /* errdetail for server log */
1520
1525 "Process %d waits for %s on %s.",
1526 MyProcPid,
1528 locktagbuf.data);
1529
1531 (errmsg_internal("sending cancel to blocking autovacuum PID %d",
1532 pid),
1533 errdetail_log("%s", logbuf.data)));
1534
1535 pfree(locktagbuf.data);
1536 pfree(logbuf.data);
1537 }
1538
1539 /* send the autovacuum worker Back to Old Kent Road */
1540 if (kill(pid, SIGINT) < 0)
1541 {
1542 /*
1543 * There's a race condition here: once we release the
1544 * ProcArrayLock, it's possible for the autovac worker to
1545 * close up shop and exit before we can do the kill().
1546 * Therefore, we do not whinge about no-such-process.
1547 * Other errors such as EPERM could conceivably happen if
1548 * the kernel recycles the PID fast enough, but such cases
1549 * seem improbable enough that it's probably best to issue
1550 * a warning if we see some other errno.
1551 */
1552 if (errno != ESRCH)
1554 (errmsg("could not send signal to process %d: %m",
1555 pid)));
1556 }
1557 }
1558
1559 /* prevent signal from being sent again more than once */
1561 }
1562
1563 /*
1564 * If awoken after the deadlock check interrupt has run, increment the
1565 * lock statistics counters and if log_lock_waits is on, then report
1566 * about the wait.
1567 */
1569 {
1570 long secs;
1571 int usecs;
1572 long msecs;
1573
1574 INJECTION_POINT("deadlock-timeout-fired", NULL);
1577 &secs, &usecs);
1578 msecs = secs * 1000 + usecs / 1000;
1579 usecs = usecs % 1000;
1580
1581 /* Increment the lock statistics counters if done waiting. */
1583 pgstat_count_lock_waits(locallock->tag.lock.locktag_type, msecs);
1584
1585 if (log_lock_waits)
1586 {
1590 const char *modename;
1591 int lockHoldersNum = 0;
1592
1596
1597 DescribeLockTag(&buf, &locallock->tag.lock);
1598 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1599 lockmode);
1600
1601 /* Gather a list of all lock holders and waiters */
1606
1608 ereport(LOG,
1609 (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1610 MyProcPid, modename, buf.data, msecs, usecs),
1611 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1612 "Processes holding the lock: %s. Wait queue: %s.",
1614 else if (deadlock_state == DS_HARD_DEADLOCK)
1615 {
1616 /*
1617 * This message is a bit redundant with the error that
1618 * will be reported subsequently, but in some cases the
1619 * error report might not make it to the log (eg, if it's
1620 * caught by an exception handler), and we want to ensure
1621 * all long-wait events get logged.
1622 */
1623 ereport(LOG,
1624 (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1625 MyProcPid, modename, buf.data, msecs, usecs),
1626 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1627 "Processes holding the lock: %s. Wait queue: %s.",
1629 }
1630
1632 {
1633 /*
1634 * Guard the "still waiting on lock" log message so it is
1635 * reported at most once while waiting for the lock.
1636 *
1637 * Without this guard, the message can be emitted whenever
1638 * the lock-wait sleep is interrupted (for example by
1639 * SIGHUP for config reload or by
1640 * client_connection_check_interval). For example, if
1641 * client_connection_check_interval is set very low (e.g.,
1642 * 100 ms), the message could be logged repeatedly,
1643 * flooding the log and making it difficult to use.
1644 */
1645 if (!logged_lock_wait)
1646 {
1647 ereport(LOG,
1648 (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1649 MyProcPid, modename, buf.data, msecs, usecs),
1650 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1651 "Processes holding the lock: %s. Wait queue: %s.",
1653 logged_lock_wait = true;
1654 }
1655 }
1657 ereport(LOG,
1658 (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1659 MyProcPid, modename, buf.data, msecs, usecs)));
1660 else
1661 {
1663
1664 /*
1665 * Currently, the deadlock checker always kicks its own
1666 * process, which means that we'll only see
1667 * PROC_WAIT_STATUS_ERROR when deadlock_state ==
1668 * DS_HARD_DEADLOCK, and there's no need to print
1669 * redundant messages. But for completeness and
1670 * future-proofing, print a message if it looks like
1671 * someone else kicked us off the lock.
1672 */
1674 ereport(LOG,
1675 (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1676 MyProcPid, modename, buf.data, msecs, usecs),
1677 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1678 "Processes holding the lock: %s. Wait queue: %s.",
1680 }
1681 pfree(buf.data);
1684 }
1685
1686 /*
1687 * At this point we might still need to wait for the lock. Reset
1688 * state so we don't print the above messages again if
1689 * log_lock_waits is on.
1690 */
1692 }
1694
1695 /*
1696 * Disable the timers, if they are still running. As in LockErrorCleanup,
1697 * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1698 * already caused QueryCancelPending to become set, we want the cancel to
1699 * be reported as a lock timeout, not a user cancel.
1700 */
1701 if (!InHotStandby)
1702 {
1703 if (LockTimeout > 0)
1704 {
1706
1708 timeouts[0].keep_indicator = false;
1709 timeouts[1].id = LOCK_TIMEOUT;
1710 timeouts[1].keep_indicator = true;
1712 }
1713 else
1715 }
1716
1717 /*
1718 * Emit the log message if recovery conflict on lock was resolved but the
1719 * startup process waited longer than deadlock_timeout for it.
1720 */
1724 NULL, false);
1725
1726 /*
1727 * We don't have to do anything else, because the awaker did all the
1728 * necessary updates of the lock table and MyProc. (The caller is
1729 * responsible for updating the local lock table.)
1730 */
1731 return myWaitStatus;
1732}
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition timestamp.c:1715
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1775
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1639
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1603
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:32
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define DEBUG1
Definition elog.h:31
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
#define INJECTION_POINT(name, arg)
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:3078
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4236
@ DS_BLOCKED_BY_AUTOVACUUM
Definition lock.h:345
@ DS_NOT_YET_CHECKED
Definition lock.h:341
@ DS_SOFT_DEADLOCK
Definition lock.h:343
#define AccessExclusiveLock
Definition lockdefs.h:43
@ LW_SHARED
Definition lwlock.h:105
void pfree(void *pointer)
Definition mcxt.c:1616
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
static char buf[DEFAULT_XLOG_SEG_SIZE]
void pgstat_count_lock_waits(uint8 locktag_type, long msecs)
#define PROC_VACUUM_FOR_WRAPAROUND
Definition proc.h:64
ProcWaitStatus
Definition proc.h:144
bool log_lock_waits
Definition proc.c:68
void GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
Definition proc.c:1941
int DeadlockTimeout
Definition proc.c:62
int LockTimeout
Definition proc.c:64
static DeadLockState CheckDeadLock(void)
Definition proc.c:1823
void CheckRecoveryConflictDeadlock(void)
Definition standby.c:907
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:626
@ RECOVERY_CONFLICT_LOCK
Definition standby.h:40
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
uint8 locktag_lockmethodid
Definition locktag.h:71
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:6830
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(), INJECTION_POINT, 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, pgstat_count_lock_waits(), 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 1748 of file proc.c.

1749{
1750 if (dlist_node_is_detached(&proc->waitLink))
1751 return;
1752
1754
1755 /* Remove process from wait queue */
1757
1758 /* Clean up process' state and pass it the ok/fail signal */
1759 proc->waitLock = NULL;
1760 proc->waitProcLock = NULL;
1761 proc->waitStatus = waitStatus;
1762 pg_atomic_write_u64(&proc->waitStart, 0);
1763
1764 /* And awaken it */
1765 SetLatch(&proc->procLatch);
1766}
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 913 of file proc.c.

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

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

Referenced by InitProcessPhase2().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

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}

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

Referenced by LockBufferForCleanup().

Variable Documentation

◆ AllProcsShmemPtr

void* AllProcsShmemPtr
static

Definition at line 75 of file proc.c.

Referenced by ProcGlobalShmemInit(), and ProcGlobalShmemRequest().

◆ AuxiliaryProcs

NON_EXEC_STATIC PGPROC* AuxiliaryProcs = NULL

◆ DeadlockTimeout

◆ FastPathLockArrayShmemPtr

void* FastPathLockArrayShmemPtr
static

Definition at line 76 of file proc.c.

Referenced by ProcGlobalShmemInit(), and ProcGlobalShmemRequest().

◆ FastPathLockArrayShmemSize

size_t FastPathLockArrayShmemSize
static

Definition at line 90 of file proc.c.

Referenced by ProcGlobalShmemInit(), and ProcGlobalShmemRequest().

◆ got_deadlock_timeout

volatile sig_atomic_t got_deadlock_timeout
static

Definition at line 93 of file proc.c.

Referenced by CheckDeadLockAlert(), and ProcSleep().

◆ IdleInTransactionSessionTimeout

int IdleInTransactionSessionTimeout = 0

Definition at line 65 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

int IdleSessionTimeout = 0

Definition at line 67 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

int LockTimeout = 0

Definition at line 64 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

bool log_lock_waits = true

Definition at line 68 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGPROC* MyProc = NULL

Definition at line 71 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(), 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(), RepackWorkerMain(), ReplicationSlotRelease(), report_recovery_conflict(), ResolveRecoveryConflictWithLock(), set_indexsafe_procflags(), SetAuthenticatedUserId(), SetDataChecksumsOff(), SetDataChecksumsOn(), SetDataChecksumsOnInProgress(), 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(), start_repack_decoding_worker(), StartTransaction(), StartupDecodingContext(), SwitchBackToLocalLatch(), SwitchToSharedLatch(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepQueueInsert(), SyncRepWaitForLSN(), TerminateOtherDBBackends(), TransactionGroupUpdateXidStatus(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), TruncateMultiXact(), vacuum_rel(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), WaitXLogInsertionsToFinish(), write_csvlog(), write_jsonlog(), and XidCacheRemoveRunningXids().

◆ PreparedXactProcs

PGPROC* PreparedXactProcs = NULL

Definition at line 78 of file proc.c.

Referenced by ProcGlobalShmemInit(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ ProcGlobalAllProcsShmemSize

size_t ProcGlobalAllProcsShmemSize
static

Definition at line 89 of file proc.c.

Referenced by ProcGlobalShmemInit(), and ProcGlobalShmemRequest().

◆ ProcGlobalShmemCallbacks

const ShmemCallbacks ProcGlobalShmemCallbacks
Initial value:
= {
.request_fn = ProcGlobalShmemRequest,
.init_fn = ProcGlobalShmemInit,
}
static void ProcGlobalShmemRequest(void *arg)
Definition proc.c:147
static void ProcGlobalShmemInit(void *arg)
Definition proc.c:221

Definition at line 83 of file proc.c.

83 {
84 .request_fn = ProcGlobalShmemRequest,
85 .init_fn = ProcGlobalShmemInit,
86};

◆ StatementTimeout

int StatementTimeout = 0

Definition at line 63 of file proc.c.

Referenced by enable_statement_timeout().

◆ TotalProcs

uint32 TotalProcs
static

◆ TransactionTimeout