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

1131{
1132 PGPROC *result = NULL;
1133 int index;
1134
1135 if (pid == 0) /* never match dummy PGPROCs */
1136 return NULL;
1137
1138 for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1139 {
1140 PGPROC *proc = &AuxiliaryProcs[index];
1141
1142 if (proc->pid == pid)
1143 {
1144 result = proc;
1145 break;
1146 }
1147 }
1148 return result;
1149}
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:97

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

1080{
1081 int proctype = DatumGetInt32(arg);
1083 PGPROC *proc;
1084
1086
1087 /* not safe if forked by system(), etc. */
1088 if (MyProc->pid != (int) getpid())
1089 elog(PANIC, "AuxiliaryProcKill() called in child process");
1090
1092
1093 Assert(MyProc == auxproc);
1094
1095 /* Release any LW locks I am holding (see notes above) */
1097
1098 /* Cancel any pending condition variable sleep, too */
1100
1101 /* look at the equivalent ProcKill() code for comments */
1104
1105 proc = MyProc;
1106 MyProc = NULL;
1108 DisownLatch(&proc->procLatch);
1109
1111
1112 /* Mark auxiliary proc no longer in use */
1113 proc->pid = 0;
1116
1117 /* Update shared estimate of spins_per_delay */
1119
1121}
#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:1323
#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 2075 of file proc.c.

2076{
2078
2079 /* If we already did it, we don't need to do it again. */
2081 return;
2082
2083 /* We had better not be a follower. */
2085
2086 /* Create single-member group, containing only ourselves. */
2092}
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 2105 of file proc.c.

2106{
2108 bool ok = false;
2109
2110 /* Group leader can't become member of group */
2111 Assert(MyProc != leader);
2112
2113 /* Can't already be a member of a group */
2115
2116 /* PID must be valid. */
2117 Assert(pid != 0);
2118
2119 /*
2120 * Get lock protecting the group fields. Note LockHashPartitionLockByProc
2121 * calculates the proc number based on the PGPROC slot without looking at
2122 * its contents, so we will acquire the correct lock even if the leader
2123 * PGPROC is in process of being recycled.
2124 */
2127
2128 /* Is this the leader we're looking for? */
2129 if (leader->pid == pid && leader->lockGroupLeader == leader)
2130 {
2131 /* OK, join the group */
2132 ok = true;
2133 MyProc->lockGroupLeader = leader;
2135 }
2137
2138 return ok;
2139}
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
Size add_size(Size s1, Size s2)
Definition mcxt.c:1733
Size mul_size(Size s1, Size s2)
Definition mcxt.c:1752
unsigned int Oid
#define FastPathLockSlotsPerBackend()
Definition proc.h:97
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 1856 of file proc.c.

1857{
1858 int i;
1860
1861 /*
1862 * Acquire exclusive lock on the entire shared lock data structures. Must
1863 * grab LWLocks in partition-number order to avoid LWLock deadlock.
1864 *
1865 * Note that the deadlock check interrupt had better not be enabled
1866 * anywhere that this process itself holds lock partition locks, else this
1867 * will wait forever. Also note that LWLockAcquire creates a critical
1868 * section, so that this routine cannot be interrupted by cancel/die
1869 * interrupts.
1870 */
1871 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
1873
1874 /*
1875 * Check to see if we've been awoken by anyone in the interim.
1876 *
1877 * If we have, we can return and resume our transaction -- happy day.
1878 * Before we are awoken the process releasing the lock grants it to us so
1879 * we know that we don't have to wait anymore.
1880 *
1881 * We check by looking to see if we've been unlinked from the wait queue.
1882 * This is safe because we hold the lock partition lock.
1883 */
1885 {
1887 goto check_done;
1888 }
1889
1890#ifdef LOCK_DEBUG
1891 if (Debug_deadlocks)
1892 DumpAllLocks();
1893#endif
1894
1895 /* Run the deadlock check */
1897
1898 if (result == DS_HARD_DEADLOCK)
1899 {
1900 /*
1901 * Oops. We have a deadlock.
1902 *
1903 * Get this process out of wait state. (Note: we could do this more
1904 * efficiently by relying on lockAwaited, but use this coding to
1905 * preserve the flexibility to kill some other transaction than the
1906 * one detecting the deadlock.)
1907 *
1908 * RemoveFromWaitQueue sets MyProc->waitStatus to
1909 * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
1910 * return.
1911 */
1914
1915 /*
1916 * We're done here. Transaction abort caused by the error that
1917 * ProcSleep will raise will cause any other locks we hold to be
1918 * released, thus allowing other processes to wake up; we don't need
1919 * to do that here. NOTE: an exception is that releasing locks we
1920 * hold doesn't consider the possibility of waiters that were blocked
1921 * behind us on the lock we just failed to get, and might now be
1922 * wakable because we're not in front of them anymore. However,
1923 * RemoveFromWaitQueue took care of waking up any such processes.
1924 */
1925 }
1926
1927 /*
1928 * And release locks. We do this in reverse order for two reasons: (1)
1929 * Anyone else who needs more than one of the locks will be trying to lock
1930 * them in increasing order; we don't want to release the other process
1931 * until it can get all the locks it needs. (2) This avoids O(N^2)
1932 * behavior inside LWLockRelease.
1933 */
1935 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
1937
1938 return result;
1939}
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:2054
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:554
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 1947 of file proc.c.

1948{
1949 int save_errno = errno;
1950
1951 got_deadlock_timeout = true;
1952
1953 /*
1954 * Have to set the latch again, even if handle_sig_alarm already did. Back
1955 * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1956 * ever would be a problem, but setting a set latch again is cheap.
1957 *
1958 * Note that, when this function runs inside procsignal_sigusr1_handler(),
1959 * the handler function sets the latch again after the latch is set here.
1960 */
1962 errno = save_errno;
1963}
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 1974 of file proc.c.

1976{
1979 LOCK *lock = locallock->lock;
1980 bool first_holder = true,
1981 first_waiter = true;
1982
1983#ifdef USE_ASSERT_CHECKING
1984 {
1985 uint32 hashcode = locallock->hashcode;
1987
1989 }
1990#endif
1991
1992 *lockHoldersNum = 0;
1993
1994 /*
1995 * Loop over the lock's procLocks to gather a list of all holders and
1996 * waiters. Thus we will be able to provide more detailed information for
1997 * lock debugging purposes.
1998 *
1999 * lock->procLocks contains all processes which hold or wait for this
2000 * lock.
2001 */
2003 {
2004 curproclock =
2005 dlist_container(PROCLOCK, lockLink, proc_iter.cur);
2006
2007 /*
2008 * We are a waiter if myProc->waitProcLock == curproclock; we are a
2009 * holder if it is NULL or something different.
2010 */
2011 if (curproclock->tag.myProc->waitProcLock == curproclock)
2012 {
2013 if (first_waiter)
2014 {
2016 curproclock->tag.myProc->pid);
2017 first_waiter = false;
2018 }
2019 else
2021 curproclock->tag.myProc->pid);
2022 }
2023 else
2024 {
2025 if (first_holder)
2026 {
2028 curproclock->tag.myProc->pid);
2029 first_holder = false;
2030 }
2031 else
2033 curproclock->tag.myProc->pid);
2034
2035 (*lockHoldersNum)++;
2036 }
2037 }
2038}
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:1079
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:875
#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:389
#define AmBackgroundWorkerProcess()
Definition miscadmin.h:390
#define AmWalSenderProcess()
Definition miscadmin.h:391
#define AmSpecialWorkerProcess()
Definition miscadmin.h:405
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 1179 of file proc.c.

1180{
1181 LOCKMODE lockmode = locallock->tag.mode;
1182 LOCK *lock = locallock->lock;
1183 PROCLOCK *proclock = locallock->proclock;
1184 uint32 hashcode = locallock->hashcode;
1190 bool early_deadlock = false;
1191 PGPROC *leader = MyProc->lockGroupLeader;
1192
1194
1195 /*
1196 * Set bitmask of locks this process already holds on this object.
1197 */
1198 myHeldLocks = MyProc->heldLocks = proclock->holdMask;
1199
1200 /*
1201 * Determine which locks we're already holding.
1202 *
1203 * If group locking is in use, locks held by members of my locking group
1204 * need to be included in myHeldLocks. This is not required for relation
1205 * extension lock which conflict among group members. However, including
1206 * them in myHeldLocks will give group members the priority to get those
1207 * locks as compared to other backends which are also trying to acquire
1208 * those locks. OTOH, we can avoid giving priority to group members for
1209 * that kind of locks, but there doesn't appear to be a clear advantage of
1210 * the same.
1211 */
1212 myProcHeldLocks = proclock->holdMask;
1214 if (leader != NULL)
1215 {
1216 dlist_iter iter;
1217
1218 dlist_foreach(iter, &lock->procLocks)
1219 {
1221
1222 otherproclock = dlist_container(PROCLOCK, lockLink, iter.cur);
1223
1224 if (otherproclock->groupLeader == leader)
1225 myHeldLocks |= otherproclock->holdMask;
1226 }
1227 }
1228
1229 /*
1230 * Determine where to add myself in the wait queue.
1231 *
1232 * Normally I should go at the end of the queue. However, if I already
1233 * hold locks that conflict with the request of any previous waiter, put
1234 * myself in the queue just in front of the first such waiter. This is not
1235 * a necessary step, since deadlock detection would move me to before that
1236 * waiter anyway; but it's relatively cheap to detect such a conflict
1237 * immediately, and avoid delaying till deadlock timeout.
1238 *
1239 * Special case: if I find I should go in front of some waiter, check to
1240 * see if I conflict with already-held locks or the requests before that
1241 * waiter. If not, then just grant myself the requested lock immediately.
1242 * This is the same as the test for immediate grant in LockAcquire, except
1243 * we are only considering the part of the wait queue before my insertion
1244 * point.
1245 */
1247 {
1249 dlist_iter iter;
1250
1252 {
1253 PGPROC *proc = dlist_container(PGPROC, waitLink, iter.cur);
1254
1255 /*
1256 * If we're part of the same locking group as this waiter, its
1257 * locks neither conflict with ours nor contribute to
1258 * aheadRequests.
1259 */
1260 if (leader != NULL && leader == proc->lockGroupLeader)
1261 continue;
1262
1263 /* Must he wait for me? */
1264 if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
1265 {
1266 /* Must I wait for him ? */
1267 if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
1268 {
1269 /*
1270 * Yes, so we have a deadlock. Easiest way to clean up
1271 * correctly is to call RemoveFromWaitQueue(), but we
1272 * can't do that until we are *on* the wait queue. So, set
1273 * a flag to check below, and break out of loop. Also,
1274 * record deadlock info for later message.
1275 */
1276 RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
1277 early_deadlock = true;
1278 break;
1279 }
1280 /* I must go before this waiter. Check special case. */
1281 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1282 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1283 proclock))
1284 {
1285 /* Skip the wait and just grant myself the lock. */
1286 GrantLock(lock, proclock, lockmode);
1287 return PROC_WAIT_STATUS_OK;
1288 }
1289
1290 /* Put myself into wait queue before conflicting process */
1291 insert_before = proc;
1292 break;
1293 }
1294 /* Nope, so advance to next waiter */
1296 }
1297 }
1298
1299 /*
1300 * If we detected deadlock, give up without waiting. This must agree with
1301 * CheckDeadLock's recovery code.
1302 */
1303 if (early_deadlock)
1305
1306 /*
1307 * At this point we know that we'd really need to sleep. If we've been
1308 * commanded not to do that, bail out.
1309 */
1310 if (dontWait)
1312
1313 /*
1314 * Insert self into queue, at the position determined above.
1315 */
1316 if (insert_before)
1318 else
1320
1321 lock->waitMask |= LOCKBIT_ON(lockmode);
1322
1323 /* Set up wait information in PGPROC object, too */
1325 MyProc->waitLock = lock;
1326 MyProc->waitProcLock = proclock;
1327 MyProc->waitLockMode = lockmode;
1328
1330
1332}
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:1666
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition lock.c:1537
#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:1897
void ResetAwaitedLock(void)
Definition lock.c:1915
void AbortStrongLockAcquire(void)
Definition lock.c:1868
LOCALLOCK * GetAwaitedLock(void)
Definition lock.c:1906
#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 PGPROC *leader;
928 dlist_head *procgloballist;
929 bool push_leader;
930 bool push_self;
931
932 Assert(MyProc != NULL);
933
934 /* not safe if forked by system(), etc. */
935 if (MyProc->pid != (int) getpid())
936 elog(PANIC, "ProcKill() called in child process");
937
938 /* Make sure we're out of the sync rep lists */
940
941#ifdef USE_ASSERT_CHECKING
942 {
943 int i;
944
945 /* Last process should have released all locks. */
946 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
948 }
949#endif
950
951 /*
952 * Release any LW locks I am holding. There really shouldn't be any, but
953 * it's cheap to check again before we cut the knees off the LWLock
954 * facility by releasing our PGPROC ...
955 */
957
958 /*
959 * Cleanup waiting for LSN if any.
960 */
962
963 /* Cancel any pending condition variable sleep, too */
965
966 /*
967 * Reset MyLatch to the process local one and disown the shared latch, so
968 * that signal handlers et al can continue using the latch after the
969 * shared latch isn't ours anymore.
970 *
971 * DisownLatch() must happen before our PGPROC can appear on a freelist: a
972 * newly-forked backend that pops our slot and calls OwnLatch() would
973 * PANIC on a still-owned latch.
974 *
975 * pgstat_reset_wait_event_storage() is intentionally deferred until after
976 * the lock-group block so that wait_event_info remains visible in our
977 * PGPROC slot while we may be observed there. It is safe to defer
978 * because our slot is not yet on any freelist at this point, and useful
979 * for testing purposes.
980 */
983
984 proc = MyProc;
985 procgloballist = proc->procgloballist;
986
987 /*
988 * Detach from any lock group of which we are a member, deciding under
989 * leader_lwlock whether we (via push_self) and/or the leader (via
990 * push_leader) need to be pushed onto a freelist. The actual pushes
991 * happen after evaluating if any of these are required, under a single
992 * ProcGlobal->freeProcsLock.
993 *
994 * The decision whether any of the freelists needs to be updated is taken
995 * under a single leader_lwlock.
996 */
997 push_leader = false;
998 push_self = true;
999 leader = NULL;
1000
1001 if (proc->lockGroupLeader != NULL)
1002 {
1004
1005 leader = proc->lockGroupLeader;
1007
1011 if (dlist_is_empty(&leader->lockGroupMembers))
1012 {
1013 leader->lockGroupLeader = NULL;
1014 if (leader != proc)
1015 {
1016 /*
1017 * We are the last follower and the leader exited earlier; its
1018 * PGPROC is still allocated and must be pushed here.
1019 */
1020 push_leader = true;
1021 proc->lockGroupLeader = NULL;
1022 }
1023 }
1024 else if (leader != proc)
1025 {
1026 /* Non-last follower; leader still present in the group. */
1027 proc->lockGroupLeader = NULL;
1028 }
1029 else
1030 {
1031 /*
1032 * We are the leader and followers remain. Skip our own push; the
1033 * last follower to exit will push us back to the freelist.
1034 */
1035 push_self = false;
1036 }
1038 }
1039
1040 /* See comment above, close to DisownLatch() */
1042
1043 MyProc = NULL;
1045
1046 /* Mark the proc no longer in use */
1047 proc->pid = 0;
1050
1052 if (push_leader)
1053 {
1054 /* Return leader PGPROC (and semaphore) to appropriate freelist */
1055 dlist_push_head(leader->procgloballist, &leader->freeProcsLink);
1056 }
1057 if (push_self)
1058 {
1059 Assert(proc->lockGroupLeader == NULL);
1060 /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
1062
1063 /* Return PGPROC structure (and semaphore) to appropriate freelist */
1064 dlist_push_tail(procgloballist, &proc->freeProcsLink);
1065 }
1066
1067 /* Update shared estimate of spins_per_delay */
1069
1071}
static void dlist_delete(dlist_node *node)
Definition ilist.h:405
void SyncRepCleanupAtProcExit(void)
Definition syncrep.c:426
void WaitLSNCleanup(void)
Definition xlogwait.c:366

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

1810{
1814
1816 return;
1817
1819 {
1820 PGPROC *proc = dlist_container(PGPROC, waitLink, miter.cur);
1821 LOCKMODE lockmode = proc->waitLockMode;
1822
1823 /*
1824 * Waken if (a) doesn't conflict with requests of earlier waiters, and
1825 * (b) doesn't conflict with already-held locks.
1826 */
1827 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1828 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1829 proc->waitProcLock))
1830 {
1831 /* OK to waken */
1832 GrantLock(lock, proc->waitProcLock, lockmode);
1833 /* removes proc from the lock's waiting process queue */
1835 }
1836 else
1837 {
1838 /*
1839 * Lock conflicts: Don't wake, but remember requested mode for
1840 * later checks.
1841 */
1842 aheadRequests |= LOCKBIT_ON(lockmode);
1843 }
1844 }
1845}
#define dclist_foreach_modify(iter, lhead)
Definition ilist.h:973
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition proc.c:1781

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:2315
#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 2060 of file proc.c.

2061{
2063 elog(ERROR, "procNumber out of range");
2064
2065 SetLatch(&GetPGProcByNumber(procNumber)->procLatch);
2066}
#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 1348 of file proc.c.

1349{
1350 LOCKMODE lockmode = locallock->tag.mode;
1351 LOCK *lock = locallock->lock;
1352 uint32 hashcode = locallock->hashcode;
1355 bool allow_autovacuum_cancel = true;
1356 bool logged_recovery_conflict = false;
1357 bool logged_lock_wait = false;
1360
1361 /* The caller must've armed the on-error cleanup mechanism */
1364
1365 /*
1366 * Now that we will successfully clean up after an ereport, it's safe to
1367 * check to see if there's a buffer pin deadlock against the Startup
1368 * process. Of course, that's only necessary if we're doing Hot Standby
1369 * and are not the Startup process ourselves.
1370 */
1373
1374 /* Reset deadlock_state before enabling the timeout handler */
1376 got_deadlock_timeout = false;
1377
1378 /*
1379 * Set timer so we can wake up after awhile and check for a deadlock. If a
1380 * deadlock is detected, the handler sets MyProc->waitStatus =
1381 * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
1382 * rather than success.
1383 *
1384 * By delaying the check until we've waited for a bit, we can avoid
1385 * running the rather expensive deadlock-check code in most cases.
1386 *
1387 * If LockTimeout is set, also enable the timeout for that. We can save a
1388 * few cycles by enabling both timeout sources in one call.
1389 *
1390 * If InHotStandby we set lock waits slightly later for clarity with other
1391 * code.
1392 */
1393 if (!InHotStandby)
1394 {
1395 if (LockTimeout > 0)
1396 {
1398
1400 timeouts[0].type = TMPARAM_AFTER;
1401 timeouts[0].delay_ms = DeadlockTimeout;
1402 timeouts[1].id = LOCK_TIMEOUT;
1403 timeouts[1].type = TMPARAM_AFTER;
1404 timeouts[1].delay_ms = LockTimeout;
1406 }
1407 else
1409
1410 /*
1411 * Use the current time obtained for the deadlock timeout timer as
1412 * waitStart (i.e., the time when this process started waiting for the
1413 * lock). Since getting the current time newly can cause overhead, we
1414 * reuse the already-obtained time to avoid that overhead.
1415 *
1416 * Note that waitStart is updated without holding the lock table's
1417 * partition lock, to avoid the overhead by additional lock
1418 * acquisition. This can cause "waitstart" in pg_locks to become NULL
1419 * for a very short period of time after the wait started even though
1420 * "granted" is false. This is OK in practice because we can assume
1421 * that users are likely to look at "waitstart" when waiting for the
1422 * lock for a long time.
1423 */
1426 }
1428 {
1429 /*
1430 * Set the wait start timestamp if logging is enabled and in hot
1431 * standby.
1432 */
1434 }
1435
1436 /*
1437 * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1438 * will not wait. But a set latch does not necessarily mean that the lock
1439 * is free now, as there are many other sources for latch sets than
1440 * somebody releasing the lock.
1441 *
1442 * We process interrupts whenever the latch has been set, so cancel/die
1443 * interrupts are processed quickly. This means we must not mind losing
1444 * control to a cancel/die interrupt here. We don't, because we have no
1445 * shared-state-change work to do after being granted the lock (the
1446 * grantor did it all). We do have to worry about canceling the deadlock
1447 * timeout and updating the locallock table, but if we lose control to an
1448 * error, LockErrorCleanup will fix that up.
1449 */
1450 do
1451 {
1452 if (InHotStandby)
1453 {
1454 bool maybe_log_conflict =
1456
1457 /* Set a timer and wait for that or for the lock to be granted */
1460
1461 /*
1462 * Emit the log message if the startup process is waiting longer
1463 * than deadlock_timeout for recovery conflict on lock.
1464 */
1466 {
1468
1471 {
1473 int cnt;
1474
1475 vxids = GetLockConflicts(&locallock->tag.lock,
1476 AccessExclusiveLock, &cnt);
1477
1478 /*
1479 * Log the recovery conflict and the list of PIDs of
1480 * backends holding the conflicting lock. Note that we do
1481 * logging even if there are no such backends right now
1482 * because the startup process here has already waited
1483 * longer than deadlock_timeout.
1484 */
1487 cnt > 0 ? vxids : NULL, true);
1489 }
1490 }
1491 }
1492 else
1493 {
1495 PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1497 /* check for deadlocks first, as that's probably log-worthy */
1499 {
1501 got_deadlock_timeout = false;
1502 }
1504 }
1505
1506 /*
1507 * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
1508 * else asynchronously. Read it just once per loop to prevent
1509 * surprising behavior (such as missing log messages).
1510 */
1511 myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
1512
1513 /*
1514 * If we are not deadlocked, but are waiting on an autovacuum-induced
1515 * task, send a signal to interrupt it.
1516 */
1518 {
1520 uint8 statusFlags;
1523
1524 /*
1525 * Grab info we need, then release lock immediately. Note this
1526 * coding means that there is a tiny chance that the process
1527 * terminates its current transaction and starts a different one
1528 * before we have a change to send the signal; the worst possible
1529 * consequence is that a for-wraparound vacuum is canceled. But
1530 * that could happen in any case unless we were to do kill() with
1531 * the lock held, which is much more undesirable.
1532 */
1534 statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1536 locktag_copy = lock->tag;
1538
1539 /*
1540 * Only do it if the worker is not working to protect against Xid
1541 * wraparound.
1542 */
1543 if ((statusFlags & PROC_IS_AUTOVACUUM) &&
1544 !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
1545 {
1546 int pid = autovac->pid;
1547
1548 /* report the case, if configured to do so */
1550 {
1552 StringInfoData logbuf; /* errdetail for server log */
1553
1558 "Process %d waits for %s on %s.",
1559 MyProcPid,
1561 locktagbuf.data);
1562
1564 (errmsg_internal("sending cancel to blocking autovacuum PID %d",
1565 pid),
1566 errdetail_log("%s", logbuf.data)));
1567
1568 pfree(locktagbuf.data);
1569 pfree(logbuf.data);
1570 }
1571
1572 /* send the autovacuum worker Back to Old Kent Road */
1573 if (kill(pid, SIGINT) < 0)
1574 {
1575 /*
1576 * There's a race condition here: once we release the
1577 * ProcArrayLock, it's possible for the autovac worker to
1578 * close up shop and exit before we can do the kill().
1579 * Therefore, we do not whinge about no-such-process.
1580 * Other errors such as EPERM could conceivably happen if
1581 * the kernel recycles the PID fast enough, but such cases
1582 * seem improbable enough that it's probably best to issue
1583 * a warning if we see some other errno.
1584 */
1585 if (errno != ESRCH)
1587 (errmsg("could not send signal to process %d: %m",
1588 pid)));
1589 }
1590 }
1591
1592 /* prevent signal from being sent again more than once */
1594 }
1595
1596 /*
1597 * If awoken after the deadlock check interrupt has run, increment the
1598 * lock statistics counters and if log_lock_waits is on, then report
1599 * about the wait.
1600 */
1602 {
1603 long secs;
1604 int usecs;
1605 long msecs;
1606
1607 INJECTION_POINT("deadlock-timeout-fired", NULL);
1610 &secs, &usecs);
1611 msecs = secs * 1000 + usecs / 1000;
1612 usecs = usecs % 1000;
1613
1614 /* Increment the lock statistics counters if done waiting. */
1616 pgstat_count_lock_waits(locallock->tag.lock.locktag_type, msecs);
1617
1618 if (log_lock_waits)
1619 {
1623 const char *modename;
1624 int lockHoldersNum = 0;
1625
1629
1630 DescribeLockTag(&buf, &locallock->tag.lock);
1631 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1632 lockmode);
1633
1634 /* Gather a list of all lock holders and waiters */
1639
1641 ereport(LOG,
1642 (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1643 MyProcPid, modename, buf.data, msecs, usecs),
1644 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1645 "Processes holding the lock: %s. Wait queue: %s.",
1647 else if (deadlock_state == DS_HARD_DEADLOCK)
1648 {
1649 /*
1650 * This message is a bit redundant with the error that
1651 * will be reported subsequently, but in some cases the
1652 * error report might not make it to the log (eg, if it's
1653 * caught by an exception handler), and we want to ensure
1654 * all long-wait events get logged.
1655 */
1656 ereport(LOG,
1657 (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1658 MyProcPid, modename, buf.data, msecs, usecs),
1659 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1660 "Processes holding the lock: %s. Wait queue: %s.",
1662 }
1663
1665 {
1666 /*
1667 * Guard the "still waiting on lock" log message so it is
1668 * reported at most once while waiting for the lock.
1669 *
1670 * Without this guard, the message can be emitted whenever
1671 * the lock-wait sleep is interrupted (for example by
1672 * SIGHUP for config reload or by
1673 * client_connection_check_interval). For example, if
1674 * client_connection_check_interval is set very low (e.g.,
1675 * 100 ms), the message could be logged repeatedly,
1676 * flooding the log and making it difficult to use.
1677 */
1678 if (!logged_lock_wait)
1679 {
1680 ereport(LOG,
1681 (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1682 MyProcPid, modename, buf.data, msecs, usecs),
1683 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1684 "Processes holding the lock: %s. Wait queue: %s.",
1686 logged_lock_wait = true;
1687 }
1688 }
1690 ereport(LOG,
1691 (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1692 MyProcPid, modename, buf.data, msecs, usecs)));
1693 else
1694 {
1696
1697 /*
1698 * Currently, the deadlock checker always kicks its own
1699 * process, which means that we'll only see
1700 * PROC_WAIT_STATUS_ERROR when deadlock_state ==
1701 * DS_HARD_DEADLOCK, and there's no need to print
1702 * redundant messages. But for completeness and
1703 * future-proofing, print a message if it looks like
1704 * someone else kicked us off the lock.
1705 */
1707 ereport(LOG,
1708 (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1709 MyProcPid, modename, buf.data, msecs, usecs),
1710 (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1711 "Processes holding the lock: %s. Wait queue: %s.",
1713 }
1714 pfree(buf.data);
1717 }
1718
1719 /*
1720 * At this point we might still need to wait for the lock. Reset
1721 * state so we don't print the above messages again if
1722 * log_lock_waits is on.
1723 */
1725 }
1727
1728 /*
1729 * Disable the timers, if they are still running. As in LockErrorCleanup,
1730 * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1731 * already caused QueryCancelPending to become set, we want the cancel to
1732 * be reported as a lock timeout, not a user cancel.
1733 */
1734 if (!InHotStandby)
1735 {
1736 if (LockTimeout > 0)
1737 {
1739
1741 timeouts[0].keep_indicator = false;
1742 timeouts[1].id = LOCK_TIMEOUT;
1743 timeouts[1].keep_indicator = true;
1745 }
1746 else
1748 }
1749
1750 /*
1751 * Emit the log message if recovery conflict on lock was resolved but the
1752 * startup process waited longer than deadlock_timeout for it.
1753 */
1757 NULL, false);
1758
1759 /*
1760 * We don't have to do anything else, because the awaker did all the
1761 * necessary updates of the lock table and MyProc. (The caller is
1762 * responsible for updating the local lock table.)
1763 */
1764 return myWaitStatus;
1765}
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition timestamp.c:1729
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition timestamp.c:1789
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1649
Datum now(PG_FUNCTION_ARGS)
Definition timestamp.c:1613
int64 TimestampTz
Definition timestamp.h:39
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
bool message_level_is_interesting(int elevel)
Definition elog.c:285
#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:3077
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4235
@ 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:1619
#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:1974
int DeadlockTimeout
Definition proc.c:62
int LockTimeout
Definition proc.c:64
static DeadLockState CheckDeadLock(void)
Definition proc.c:1856
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:6834
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 1781 of file proc.c.

1782{
1783 if (dlist_node_is_detached(&proc->waitLink))
1784 return;
1785
1787
1788 /* Remove process from wait queue */
1790
1791 /* Clean up process' state and pass it the ok/fail signal */
1792 proc->waitLock = NULL;
1793 proc->waitProcLock = NULL;
1794 proc->waitStatus = waitStatus;
1795 pg_atomic_write_u64(&proc->waitStart, 0);
1796
1797 /* And awaken it */
1798 SetLatch(&proc->procLatch);
1799}
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