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

1161{
1162 PGPROC *result = NULL;
1163 int index;
1164
1165 if (pid == 0) /* never match dummy PGPROCs */
1166 return NULL;
1167
1168 for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1169 {
1170 PGPROC *proc = &AuxiliaryProcs[index];
1171
1172 if (proc->pid == pid)
1173 {
1174 result = proc;
1175 break;
1176 }
1177 }
1178 return result;
1179}
uint32 result
static int fb(int x)
#define NUM_AUXILIARY_PROCS
Definition proc.h:529
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 1095 of file proc.c.

1096{
1097 int proctype = DatumGetInt32(arg);
1099 PGPROC *proc;
1100
1102
1103 /* not safe if forked by system(), etc. */
1104 if (MyProc->pid != (int) getpid())
1105 elog(PANIC, "AuxiliaryProcKill() called in child process");
1106
1108
1109 Assert(MyProc == auxproc);
1110
1111 /* Release any LW locks I am holding (see notes above) */
1113
1114 /* Cancel any pending condition variable sleep, too */
1116
1117 /* look at the equivalent ProcKill() code for comments */
1120
1121 /*
1122 * If this was one of the aux processes advertised in ProcGlobal, clear it
1123 */
1125 {
1128 }
1130 {
1133 }
1134
1135 proc = MyProc;
1136 MyProc = NULL;
1138 DisownLatch(&proc->procLatch);
1139
1141
1142 /* Mark auxiliary proc no longer in use */
1143 proc->pid = 0;
1146
1147 /* Update shared estimate of spins_per_delay */
1149
1151}
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:269
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition atomics.h:232
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:308
#define Assert(condition)
Definition c.h:1002
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
@ B_WAL_WRITER
Definition miscadmin.h:371
@ B_CHECKPOINTER
Definition miscadmin.h:366
BackendType MyBackendType
Definition miscinit.c:65
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::@134 vxid
Latch procLatch
Definition proc.h:256
pg_atomic_uint32 checkpointerProc
Definition proc.h:489
slock_t freeProcsLock
Definition proc.h:468
int spins_per_delay
Definition proc.h:494
pg_atomic_uint32 walwriterProc
Definition proc.h:488
#define InvalidTransactionId
Definition transam.h:31
void pgstat_reset_wait_event_storage(void)
Definition wait_event.c:331

References arg, Assert, AuxiliaryProcs, B_CHECKPOINTER, B_WAL_WRITER, PROC_HDR::checkpointerProc, ConditionVariableCancelSleep(), DatumGetInt32(), DisownLatch(), elog, fb(), PROC_HDR::freeProcsLock, INVALID_PROC_NUMBER, InvalidTransactionId, LWLockReleaseAll(), PGPROC::lxid, MyBackendType, MyProc, MyProcNumber, NUM_AUXILIARY_PROCS, PANIC, pg_atomic_read_u32(), pg_atomic_write_u32(), 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(), PGPROC::vxid, and PROC_HDR::walwriterProc.

Referenced by InitAuxiliaryProcess().

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 2106 of file proc.c.

2107{
2109
2110 /* If we already did it, we don't need to do it again. */
2112 return;
2113
2114 /* We had better not be a follower. */
2116
2117 /* Create single-member group, containing only ourselves. */
2123}
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 2136 of file proc.c.

2137{
2139 bool ok = false;
2140
2141 /* Group leader can't become member of group */
2142 Assert(MyProc != leader);
2143
2144 /* Can't already be a member of a group */
2146
2147 /* PID must be valid. */
2148 Assert(pid != 0);
2149
2150 /*
2151 * Get lock protecting the group fields. Note LockHashPartitionLockByProc
2152 * calculates the proc number based on the PGPROC slot without looking at
2153 * its contents, so we will acquire the correct lock even if the leader
2154 * PGPROC is in process of being recycled.
2155 */
2158
2159 /* Is this the leader we're looking for? */
2160 if (leader->pid == pid && leader->lockGroupLeader == leader)
2161 {
2162 /* OK, join the group */
2163 ok = true;
2164 MyProc->lockGroupLeader = leader;
2166 }
2168
2169 return ok;
2170}
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:955
uint64_t uint64
Definition c.h:684
size_t Size
Definition c.h:748
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 1887 of file proc.c.

1888{
1889 int i;
1891
1892 /*
1893 * Acquire exclusive lock on the entire shared lock data structures. Must
1894 * grab LWLocks in partition-number order to avoid LWLock deadlock.
1895 *
1896 * Note that the deadlock check interrupt had better not be enabled
1897 * anywhere that this process itself holds lock partition locks, else this
1898 * will wait forever. Also note that LWLockAcquire creates a critical
1899 * section, so that this routine cannot be interrupted by cancel/die
1900 * interrupts.
1901 */
1902 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
1904
1905 /*
1906 * Check to see if we've been awoken by anyone in the interim.
1907 *
1908 * If we have, we can return and resume our transaction -- happy day.
1909 * Before we are awoken the process releasing the lock grants it to us so
1910 * we know that we don't have to wait anymore.
1911 *
1912 * We check by looking to see if we've been unlinked from the wait queue.
1913 * This is safe because we hold the lock partition lock.
1914 */
1916 {
1918 goto check_done;
1919 }
1920
1921#ifdef LOCK_DEBUG
1922 if (Debug_deadlocks)
1923 DumpAllLocks();
1924#endif
1925
1926 /* Run the deadlock check */
1928
1929 if (result == DS_HARD_DEADLOCK)
1930 {
1931 /*
1932 * Oops. We have a deadlock.
1933 *
1934 * Get this process out of wait state. (Note: we could do this more
1935 * efficiently by relying on lockAwaited, but use this coding to
1936 * preserve the flexibility to kill some other transaction than the
1937 * one detecting the deadlock.)
1938 *
1939 * RemoveFromWaitQueue sets MyProc->waitStatus to
1940 * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
1941 * return.
1942 */
1945
1946 /*
1947 * We're done here. Transaction abort caused by the error that
1948 * ProcSleep will raise will cause any other locks we hold to be
1949 * released, thus allowing other processes to wake up; we don't need
1950 * to do that here. NOTE: an exception is that releasing locks we
1951 * hold doesn't consider the possibility of waiters that were blocked
1952 * behind us on the lock we just failed to get, and might now be
1953 * wakable because we're not in front of them anymore. However,
1954 * RemoveFromWaitQueue took care of waking up any such processes.
1955 */
1956 }
1957
1958 /*
1959 * And release locks. We do this in reverse order for two reasons: (1)
1960 * Anyone else who needs more than one of the locks will be trying to lock
1961 * them in increasing order; we don't want to release the other process
1962 * until it can get all the locks it needs. (2) This avoids O(N^2)
1963 * behavior inside LWLockRelease.
1964 */
1966 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
1968
1969 return result;
1970}
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 1978 of file proc.c.

1979{
1980 int save_errno = errno;
1981
1982 got_deadlock_timeout = true;
1983
1984 /*
1985 * Have to set the latch again, even if handle_sig_alarm already did. Back
1986 * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1987 * ever would be a problem, but setting a set latch again is cheap.
1988 *
1989 * Note that, when this function runs inside procsignal_sigusr1_handler(),
1990 * the handler function sets the latch again after the latch is set here.
1991 */
1993 errno = save_errno;
1994}
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 2005 of file proc.c.

2007{
2010 LOCK *lock = locallock->lock;
2011 bool first_holder = true,
2012 first_waiter = true;
2013
2014#ifdef USE_ASSERT_CHECKING
2015 {
2016 uint32 hashcode = locallock->hashcode;
2018
2020 }
2021#endif
2022
2023 *lockHoldersNum = 0;
2024
2025 /*
2026 * Loop over the lock's procLocks to gather a list of all holders and
2027 * waiters. Thus we will be able to provide more detailed information for
2028 * lock debugging purposes.
2029 *
2030 * lock->procLocks contains all processes which hold or wait for this
2031 * lock.
2032 */
2034 {
2035 curproclock =
2036 dlist_container(PROCLOCK, lockLink, proc_iter.cur);
2037
2038 /*
2039 * We are a waiter if myProc->waitProcLock == curproclock; we are a
2040 * holder if it is NULL or something different.
2041 */
2042 if (curproclock->tag.myProc->waitProcLock == curproclock)
2043 {
2044 if (first_waiter)
2045 {
2047 curproclock->tag.myProc->pid);
2048 first_waiter = false;
2049 }
2050 else
2052 curproclock->tag.myProc->pid);
2053 }
2054 else
2055 {
2056 if (first_holder)
2057 {
2059 curproclock->tag.myProc->pid);
2060 first_holder = false;
2061 }
2062 else
2064 curproclock->tag.myProc->pid);
2065
2066 (*lockHoldersNum)++;
2067 }
2068 }
2069}
uint32_t uint32
Definition c.h:683
#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 781 of file proc.c.

782{
783 /* use volatile pointer to prevent code rearrangement */
784 volatile PROC_HDR *procglobal = ProcGlobal;
785
787}
int startupBufferPinWaitBufId
Definition proc.h:496

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

Referenced by HoldingBufferPinThatDelaysRecovery().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int nfree 
)

Definition at line 797 of file proc.c.

798{
799 dlist_iter iter;
800
801 Assert(n > 0);
802 Assert(nfree);
803
805
806 *nfree = 0;
808 {
809 (*nfree)++;
810 if (*nfree == n)
811 break;
812 }
813
815
816 return (*nfree == n);
817}
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 623 of file proc.c.

624{
626 int proctype;
627
628 /*
629 * ProcGlobal should be set up already (if we are a backend, we inherit
630 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
631 */
632 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
633 elog(PANIC, "proc header uninitialized");
634
635 if (MyProc != NULL)
636 elog(ERROR, "you already exist");
637
640
641 /*
642 * We use the freeProcsLock to protect assignment and releasing of
643 * AuxiliaryProcs entries.
644 *
645 * While we are holding the spinlock, also copy the current shared
646 * estimate of spins_per_delay to local storage.
647 */
649
651
652 /*
653 * Find a free auxproc ... *big* trouble if there isn't one ...
654 */
656 {
658 if (auxproc->pid == 0)
659 break;
660 }
662 {
664 elog(FATAL, "all AuxiliaryProcs are in use");
665 }
666
667 /* Mark auxiliary proc as in use by me */
668 auxproc->pid = MyProcPid;
669
671
672 MyProc = auxproc;
674
675 /*
676 * Initialize all fields of MyProc, except for those previously
677 * initialized by ProcGlobalShmemInit.
678 */
681 MyProc->fpVXIDLock = false;
692 MyProc->statusFlags = 0;
694 MyProc->lwWaitMode = 0;
699#ifdef USE_ASSERT_CHECKING
700 {
701 int i;
702
703 /* Last process should have released all locks. */
704 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
706 }
707#endif
709
710 /*
711 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
712 * on it. That allows us to repoint the process latch, which so far
713 * points to process local one, to the shared one.
714 */
717
718 /* now that we have a proc, report wait events to shared memory */
720
721 /* Check that group locking fields are in a proper initial state. */
724
725 /*
726 * We might be reusing a semaphore that belonged to a failed process. So
727 * be careful and reinitialize its value here. (This is not strictly
728 * necessary anymore, but seems like a good idea for cleanliness.)
729 */
731
732 /* Some aux processes are also advertised in ProcGlobal */
737
738 /*
739 * Arrange to clean up at process exit.
740 */
742
743 /*
744 * Now that we have a PGPROC, we could try to acquire lightweight locks.
745 * Initialize local state needed for them. (Heavyweight locks cannot be
746 * acquired in aux processes.)
747 */
749
750#ifdef EXEC_BACKEND
751
752 /*
753 * Initialize backend-local pointers to all the shared data structures.
754 * (We couldn't do this until now because it needs LWLocks.)
755 */
758#endif
759}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:480
#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
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:507
@ 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:1095
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:319

References Assert, AuxiliaryProcKill(), AuxiliaryProcs, B_CHECKPOINTER, B_WAL_WRITER, PGPROC::backendType, PROC_HDR::checkpointerProc, 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, PROC_HDR::walwriterProc, PGPROC::xid, and PGPROC::xmin.

Referenced by AuxiliaryProcessMainCommon().

◆ InitProcess()

void InitProcess ( void  )

Definition at line 393 of file proc.c.

394{
395 dlist_head *procgloballist;
396
397 /*
398 * ProcGlobal should be set up already (if we are a backend, we inherit
399 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
400 */
401 if (ProcGlobal == NULL)
402 elog(PANIC, "proc header uninitialized");
403
404 if (MyProc != NULL)
405 elog(ERROR, "you already exist");
406
407 /*
408 * Before we start accessing the shared memory in a serious way, mark
409 * ourselves as an active postmaster child; this is so that the postmaster
410 * can detect it if we exit without cleaning up.
411 */
414
415 /*
416 * Decide which list should supply our PGPROC. This logic must match the
417 * way the freelists were constructed in ProcGlobalShmemInit().
418 */
420 procgloballist = &ProcGlobal->autovacFreeProcs;
421 else if (AmBackgroundWorkerProcess())
422 procgloballist = &ProcGlobal->bgworkerFreeProcs;
423 else if (AmWalSenderProcess())
424 procgloballist = &ProcGlobal->walsenderFreeProcs;
425 else
426 procgloballist = &ProcGlobal->freeProcs;
427
428 /*
429 * Try to get a proc struct from the appropriate free list. If this
430 * fails, we must be out of PGPROC structures (not to mention semaphores).
431 *
432 * While we are holding the spinlock, also copy the current shared
433 * estimate of spins_per_delay to local storage.
434 */
436
438
439 if (!dlist_is_empty(procgloballist))
440 {
441 MyProc = dlist_container(PGPROC, freeProcsLink, dlist_pop_head_node(procgloballist));
443 }
444 else
445 {
446 /*
447 * If we reach here, all the PGPROCs are in use. This is one of the
448 * possible places to detect "too many backends", so give the standard
449 * error message. XXX do we need to give a different failure message
450 * in the autovacuum case?
451 */
453 if (AmWalSenderProcess())
456 errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
460 errmsg("sorry, too many clients already")));
461 }
463
464 /*
465 * Cross-check that the PGPROC is of the type we expect; if this were not
466 * the case, it would get returned to the wrong list.
467 */
468 Assert(MyProc->procgloballist == procgloballist);
469
470 /*
471 * Initialize all fields of MyProc, except for those previously
472 * initialized by ProcGlobalShmemInit.
473 */
476 MyProc->fpVXIDLock = false;
483 /* databaseId and roleId will be filled in later */
489 MyProc->statusFlags = 0;
490 /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
494 MyProc->lwWaitMode = 0;
499#ifdef USE_ASSERT_CHECKING
500 {
501 int i;
502
503 /* Last process should have released all locks. */
504 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
506 }
507#endif
509
510 /* Initialize fields for sync rep */
514
515 /* Initialize fields for group XID clearing. */
519
520 /* Check that group locking fields are in a proper initial state. */
523
524 /* Initialize wait event information. */
526
527 /* Initialize fields for group transaction status update. */
528 MyProc->clogGroupMember = false;
534
535 /*
536 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
537 * on it. That allows us to repoint the process latch, which so far
538 * points to process local one, to the shared one.
539 */
542
543 /* now that we have a proc, report wait events to shared memory */
545
546 /*
547 * We might be reusing a semaphore that belonged to a failed process. So
548 * be careful and reinitialize its value here. (This is not strictly
549 * necessary anymore, but seems like a good idea for cleanliness.)
550 */
552
553 /* autovacuum launcher is specially advertised in ProcGlobal */
556
557 /*
558 * Arrange to clean up at backend exit.
559 */
561
562 /*
563 * Now that we have a PGPROC, we could try to acquire locks, so initialize
564 * local state needed for LWLocks, and the deadlock checker.
565 */
568
569#ifdef EXEC_BACKEND
570
571 /*
572 * Initialize backend-local pointers to all the shared data structures.
573 * (We couldn't do this until now because it needs LWLocks.)
574 */
577#endif
578}
#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
@ B_AUTOVAC_LAUNCHER
Definition miscadmin.h:347
static char * errmsg
#define PROC_IS_AUTOVACUUM
Definition proc.h:61
static void ProcKill(int code, Datum arg)
Definition proc.c:934
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
pg_atomic_uint32 avLauncherProc
Definition proc.h:491
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, PROC_HDR::avLauncherProc, B_AUTOVAC_LAUNCHER, 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 588 of file proc.c.

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

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

1210{
1211 LOCKMODE lockmode = locallock->tag.mode;
1212 LOCK *lock = locallock->lock;
1213 PROCLOCK *proclock = locallock->proclock;
1214 uint32 hashcode = locallock->hashcode;
1220 bool early_deadlock = false;
1221 PGPROC *leader = MyProc->lockGroupLeader;
1222
1224
1225 /*
1226 * Set bitmask of locks this process already holds on this object.
1227 */
1228 myHeldLocks = MyProc->heldLocks = proclock->holdMask;
1229
1230 /*
1231 * Determine which locks we're already holding.
1232 *
1233 * If group locking is in use, locks held by members of my locking group
1234 * need to be included in myHeldLocks. This is not required for relation
1235 * extension lock which conflict among group members. However, including
1236 * them in myHeldLocks will give group members the priority to get those
1237 * locks as compared to other backends which are also trying to acquire
1238 * those locks. OTOH, we can avoid giving priority to group members for
1239 * that kind of locks, but there doesn't appear to be a clear advantage of
1240 * the same.
1241 */
1242 myProcHeldLocks = proclock->holdMask;
1244 if (leader != NULL)
1245 {
1246 dlist_iter iter;
1247
1248 dlist_foreach(iter, &lock->procLocks)
1249 {
1251
1252 otherproclock = dlist_container(PROCLOCK, lockLink, iter.cur);
1253
1254 if (otherproclock->groupLeader == leader)
1255 myHeldLocks |= otherproclock->holdMask;
1256 }
1257 }
1258
1259 /*
1260 * Determine where to add myself in the wait queue.
1261 *
1262 * Normally I should go at the end of the queue. However, if I already
1263 * hold locks that conflict with the request of any previous waiter, put
1264 * myself in the queue just in front of the first such waiter. This is not
1265 * a necessary step, since deadlock detection would move me to before that
1266 * waiter anyway; but it's relatively cheap to detect such a conflict
1267 * immediately, and avoid delaying till deadlock timeout.
1268 *
1269 * Special case: if I find I should go in front of some waiter, check to
1270 * see if I conflict with already-held locks or the requests before that
1271 * waiter. If not, then just grant myself the requested lock immediately.
1272 * This is the same as the test for immediate grant in LockAcquire, except
1273 * we are only considering the part of the wait queue before my insertion
1274 * point.
1275 */
1277 {
1279 dlist_iter iter;
1280
1282 {
1283 PGPROC *proc = dlist_container(PGPROC, waitLink, iter.cur);
1284
1285 /*
1286 * If we're part of the same locking group as this waiter, its
1287 * locks neither conflict with ours nor contribute to
1288 * aheadRequests.
1289 */
1290 if (leader != NULL && leader == proc->lockGroupLeader)
1291 continue;
1292
1293 /* Must he wait for me? */
1294 if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
1295 {
1296 /* Must I wait for him ? */
1297 if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
1298 {
1299 /*
1300 * Yes, so we have a deadlock. Easiest way to clean up
1301 * correctly is to call RemoveFromWaitQueue(), but we
1302 * can't do that until we are *on* the wait queue. So, set
1303 * a flag to check below, and break out of loop. Also,
1304 * record deadlock info for later message.
1305 */
1306 RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
1307 early_deadlock = true;
1308 break;
1309 }
1310 /* I must go before this waiter. Check special case. */
1311 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1312 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1313 proclock))
1314 {
1315 /* Skip the wait and just grant myself the lock. */
1316 GrantLock(lock, proclock, lockmode);
1317 return PROC_WAIT_STATUS_OK;
1318 }
1319
1320 /* Put myself into wait queue before conflicting process */
1321 insert_before = proc;
1322 break;
1323 }
1324 /* Nope, so advance to next waiter */
1326 }
1327 }
1328
1329 /*
1330 * If we detected deadlock, give up without waiting. This must agree with
1331 * CheckDeadLock's recovery code.
1332 */
1333 if (early_deadlock)
1335
1336 /*
1337 * At this point we know that we'd really need to sleep. If we've been
1338 * commanded not to do that, bail out.
1339 */
1340 if (dontWait)
1342
1343 /*
1344 * Insert self into queue, at the position determined above.
1345 */
1346 if (insert_before)
1348 else
1350
1351 lock->waitMask |= LOCKBIT_ON(lockmode);
1352
1353 /* Set up wait information in PGPROC object, too */
1355 MyProc->waitLock = lock;
1356 MyProc->waitProcLock = proclock;
1357 MyProc->waitLockMode = lockmode;
1358
1360
1362}
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 828 of file proc.c.

829{
833
835
837
838 /* Nothing to do if we weren't waiting for a lock */
840 if (lockAwaited == NULL)
841 {
843 return;
844 }
845
846 /*
847 * Turn off the deadlock and lock timeout timers, if they are still
848 * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
849 * indicator flag, since this function is executed before
850 * ProcessInterrupts when responding to SIGINT; else we'd lose the
851 * knowledge that the SIGINT came from a lock timeout and not an external
852 * source.
853 */
855 timeouts[0].keep_indicator = false;
856 timeouts[1].id = LOCK_TIMEOUT;
857 timeouts[1].keep_indicator = true;
859
860 /* Unlink myself from the wait queue, if on it (might not be anymore!) */
863
865 {
866 /* We could not have been granted the lock yet */
868 }
869 else
870 {
871 /*
872 * Somebody kicked us off the lock queue already. Perhaps they
873 * granted us the lock, or perhaps they detected a deadlock. If they
874 * did grant us the lock, we'd better remember it in our local lock
875 * table.
876 */
879 }
880
882
884
886}
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
248
249 ptr = AllProcsShmemPtr;
251 MemSet(ptr, 0, requestSize);
252
253 /* Carve out the allProcs array from the shared memory area */
254 procs = (PGPROC *) ptr;
255 ptr = ptr + TotalProcs * sizeof(PGPROC);
256
257 ProcGlobal->allProcs = procs;
258 /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
260
261 /*
262 * Carve out arrays mirroring PGPROC fields in a dense manner. See
263 * PROC_HDR.
264 *
265 * XXX: It might make sense to increase padding for these arrays, given
266 * how hotly they are accessed.
267 */
268 ProcGlobal->xids = (TransactionId *) ptr;
269 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
270
272 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
273
274 ProcGlobal->statusFlags = (uint8 *) ptr;
275 ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
276
277 /* make sure we didn't overflow */
278 Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
279
280 /*
281 * Initialize arrays for fast-path locks. Those are variable-length, so
282 * can't be included in PGPROC directly. We allocate a separate piece of
283 * shared memory and then divide that between backends.
284 */
287
291
292 /* For asserts checking we did not overflow. */
294
295 /* Initialize semaphores */
297
298 for (i = 0; i < TotalProcs; i++)
299 {
300 PGPROC *proc = &procs[i];
301
302 /* Common initialization for all PGPROCs, regardless of type. */
303
304 /*
305 * Set the fast-path lock arrays, and move the pointer. We interleave
306 * the two arrays, to (hopefully) get some locality for each backend.
307 */
308 proc->fpLockBits = (uint64 *) fpPtr;
310
311 proc->fpRelId = (Oid *) fpPtr;
313
315
316 /*
317 * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
318 * dummy PGPROCs don't need these though - they're never associated
319 * with a real process
320 */
322 {
323 proc->sem = PGSemaphoreCreate();
324 InitSharedLatch(&(proc->procLatch));
326 }
327
328 /*
329 * Newly created PGPROCs for normal backends, autovacuum workers,
330 * special workers, bgworkers, and walsenders must be queued up on the
331 * appropriate free list. Because there can only ever be a small,
332 * fixed number of auxiliary processes, no free list is used in that
333 * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs
334 * for prepared transactions are added to a free list by
335 * TwoPhaseShmemInit().
336 */
337 if (i < MaxConnections)
338 {
339 /* PGPROC for normal backend, add to freeProcs list */
342 }
344 {
345 /* PGPROC for AV or special worker, add to autovacFreeProcs list */
348 }
350 {
351 /* PGPROC for bgworker, add to bgworkerFreeProcs list */
354 }
355 else if (i < MaxBackends)
356 {
357 /* PGPROC for walsender, add to walsenderFreeProcs list */
360 }
361
362 /* Initialize myProcLocks[] shared memory queues. */
363 for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
364 dlist_init(&(proc->myProcLocks[j]));
365
366 /* Initialize lockGroupMembers list. */
368
369 /*
370 * Initialize the atomic variables, otherwise, it won't be safe to
371 * access them for backends that aren't currently in use.
372 */
375 pg_atomic_init_u64(&(proc->waitStart), 0);
376 }
377
378 /* Should have consumed exactly the expected amount of fast-path memory. */
380
381 /*
382 * Save pointers to the blocks of PGPROC structures reserved for auxiliary
383 * processes and prepared transactions.
384 */
385 AuxiliaryProcs = &procs[MaxBackends];
387}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition atomics.h:214
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:448
int autovacuum_worker_slots
Definition autovacuum.c:124
uint8_t uint8
Definition c.h:681
#define MemSet(start, val, len)
Definition c.h:1147
uint32 TransactionId
Definition c.h:795
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:531
#define NUM_SPECIAL_WORKER_PROCS
Definition proc.h:516
#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
PGPROC * allProcs
Definition proc.h:441
pg_atomic_uint32 clogGroupFirst
Definition proc.h:482
TransactionId * xids
Definition proc.h:444
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::avLauncherProc, 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 934 of file proc.c.

935{
936 PGPROC *proc;
937 PGPROC *leader;
938 dlist_head *procgloballist;
939 bool push_leader;
940 bool push_self;
941
942 Assert(MyProc != NULL);
943
944 /* not safe if forked by system(), etc. */
945 if (MyProc->pid != (int) getpid())
946 elog(PANIC, "ProcKill() called in child process");
947
948 /* Make sure we're out of the sync rep lists */
950
951#ifdef USE_ASSERT_CHECKING
952 {
953 int i;
954
955 /* Last process should have released all locks. */
956 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
958 }
959#endif
960
961 /*
962 * Release any LW locks I am holding. There really shouldn't be any, but
963 * it's cheap to check again before we cut the knees off the LWLock
964 * facility by releasing our PGPROC ...
965 */
967
968 /*
969 * Cleanup waiting for LSN if any.
970 */
972
973 /* Cancel any pending condition variable sleep, too */
975
976 /*
977 * Reset MyLatch to the process local one and disown the shared latch, so
978 * that signal handlers et al can continue using the latch after the
979 * shared latch isn't ours anymore.
980 *
981 * DisownLatch() must happen before our PGPROC can appear on a freelist: a
982 * newly-forked backend that pops our slot and calls OwnLatch() would
983 * PANIC on a still-owned latch.
984 *
985 * pgstat_reset_wait_event_storage() is intentionally deferred until after
986 * the lock-group block so that wait_event_info remains visible in our
987 * PGPROC slot while we may be observed there. It is safe to defer
988 * because our slot is not yet on any freelist at this point, and useful
989 * for testing purposes.
990 */
993
995 {
998 }
999
1000 proc = MyProc;
1001 procgloballist = proc->procgloballist;
1002
1003 /*
1004 * Detach from any lock group of which we are a member, deciding under
1005 * leader_lwlock whether we (via push_self) and/or the leader (via
1006 * push_leader) need to be pushed onto a freelist. The actual pushes
1007 * happen after evaluating if any of these are required, under a single
1008 * ProcGlobal->freeProcsLock.
1009 *
1010 * The decision whether any of the freelists needs to be updated is taken
1011 * under a single leader_lwlock.
1012 */
1013 push_leader = false;
1014 push_self = true;
1015 leader = NULL;
1016
1017 if (proc->lockGroupLeader != NULL)
1018 {
1020
1021 leader = proc->lockGroupLeader;
1023
1027 if (dlist_is_empty(&leader->lockGroupMembers))
1028 {
1029 leader->lockGroupLeader = NULL;
1030 if (leader != proc)
1031 {
1032 /*
1033 * We are the last follower and the leader exited earlier; its
1034 * PGPROC is still allocated and must be pushed here.
1035 */
1036 push_leader = true;
1037 proc->lockGroupLeader = NULL;
1038 }
1039 }
1040 else if (leader != proc)
1041 {
1042 /* Non-last follower; leader still present in the group. */
1043 proc->lockGroupLeader = NULL;
1044 }
1045 else
1046 {
1047 /*
1048 * We are the leader and followers remain. Skip our own push; the
1049 * last follower to exit will push us back to the freelist.
1050 */
1051 push_self = false;
1052 }
1054 }
1055
1056 /* See comment above, close to DisownLatch() */
1058
1059 MyProc = NULL;
1061
1062 /* Mark the proc no longer in use */
1063 proc->pid = 0;
1066
1068 if (push_leader)
1069 {
1070 /* Return leader PGPROC (and semaphore) to appropriate freelist */
1071 dlist_push_head(leader->procgloballist, &leader->freeProcsLink);
1072 }
1073 if (push_self)
1074 {
1075 Assert(proc->lockGroupLeader == NULL);
1076 /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
1078
1079 /* Return PGPROC structure (and semaphore) to appropriate freelist */
1080 dlist_push_tail(procgloballist, &proc->freeProcsLink);
1081 }
1082
1083 /* Update shared estimate of spins_per_delay */
1085
1087}
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, PROC_HDR::avLauncherProc, B_AUTOVAC_LAUNCHER, 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, MyBackendType, MyProc, PGPROC::myProcLocks, MyProcNumber, NUM_LOCK_PARTITIONS, PANIC, pg_atomic_read_u32(), pg_atomic_write_u32(), 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 1840 of file proc.c.

1841{
1845
1847 return;
1848
1850 {
1851 PGPROC *proc = dlist_container(PGPROC, waitLink, miter.cur);
1852 LOCKMODE lockmode = proc->waitLockMode;
1853
1854 /*
1855 * Waken if (a) doesn't conflict with requests of earlier waiters, and
1856 * (b) doesn't conflict with already-held locks.
1857 */
1858 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1859 !LockCheckConflicts(lockMethodTable, lockmode, lock,
1860 proc->waitProcLock))
1861 {
1862 /* OK to waken */
1863 GrantLock(lock, proc->waitProcLock, lockmode);
1864 /* removes proc from the lock's waiting process queue */
1866 }
1867 else
1868 {
1869 /*
1870 * Lock conflicts: Don't wake, but remember requested mode for
1871 * later checks.
1872 */
1873 aheadRequests |= LOCKBIT_ON(lockmode);
1874 }
1875 }
1876}
#define dclist_foreach_modify(iter, lhead)
Definition ilist.h:973
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition proc.c:1812

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

907{
908 if (!MyProc)
909 return;
910 /* If waiting, get off wait queue (should only be needed after error) */
912 /* Release standard locks, including session-level if aborting */
914 /* Release transaction-level advisory locks */
916}
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:828

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 2091 of file proc.c.

2092{
2094 elog(ERROR, "procNumber out of range");
2095
2096 SetLatch(&GetPGProcByNumber(procNumber)->procLatch);
2097}
#define GetPGProcByNumber(n)
Definition proc.h:506

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

Referenced by ReleasePredicateLocks(), and WakePinCountWaiter().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock)

Definition at line 1378 of file proc.c.

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

1813{
1814 if (dlist_node_is_detached(&proc->waitLink))
1815 return;
1816
1818
1819 /* Remove process from wait queue */
1821
1822 /* Clean up process' state and pass it the ok/fail signal */
1823 proc->waitLock = NULL;
1824 proc->waitProcLock = NULL;
1825 proc->waitStatus = waitStatus;
1826 pg_atomic_write_u64(&proc->waitStart, 0);
1827
1828 /* And awaken it */
1829 SetLatch(&proc->procLatch);
1830}
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 923 of file proc.c.

924{
925 Assert(MyProc != NULL);
927}
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 769 of file proc.c.

770{
771 /* use volatile pointer to prevent code rearrangement */
772 volatile PROC_HDR *procglobal = ProcGlobal;
773
775}

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