PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
proc.h File Reference
#include "access/clog.h"
#include "access/xlogdefs.h"
#include "lib/ilist.h"
#include "storage/latch.h"
#include "storage/lock.h"
#include "storage/pg_sema.h"
#include "storage/proclist_types.h"
#include "storage/procnumber.h"
Include dependency graph for proc.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  XidCacheStatus
 
struct  XidCache
 
struct  PGPROC
 
struct  PROC_HDR
 

Macros

#define PGPROC_MAX_CACHED_SUBXIDS   64 /* XXX guessed-at value */
 
#define PROC_IS_AUTOVACUUM   0x01 /* is it an autovac worker? */
 
#define PROC_IN_VACUUM   0x02 /* currently running lazy vacuum */
 
#define PROC_IN_SAFE_IC
 
#define PROC_VACUUM_FOR_WRAPAROUND   0x08 /* set by autovac only */
 
#define PROC_IN_LOGICAL_DECODING
 
#define PROC_AFFECTS_ALL_HORIZONS
 
#define PROC_VACUUM_STATE_MASK    (PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND)
 
#define PROC_XMIN_FLAGS   (PROC_IN_VACUUM | PROC_IN_SAFE_IC)
 
#define FP_LOCK_GROUPS_PER_BACKEND_MAX   1024
 
#define FP_LOCK_SLOTS_PER_GROUP   16 /* don't change */
 
#define FastPathLockSlotsPerBackend()    (FP_LOCK_SLOTS_PER_GROUP * FastPathLockGroupsPerBackend)
 
#define DELAY_CHKPT_START   (1<<0)
 
#define DELAY_CHKPT_COMPLETE   (1<<1)
 
#define GetPGProcByNumber(n)   (&ProcGlobal->allProcs[(n)])
 
#define GetNumberFromPGProc(proc)   ((proc) - &ProcGlobal->allProcs[0])
 
#define NUM_SPECIAL_WORKER_PROCS   2
 
#define MAX_IO_WORKERS   32
 
#define NUM_AUXILIARY_PROCS   (6 + MAX_IO_WORKERS)
 

Typedefs

typedef struct XidCacheStatus XidCacheStatus
 
typedef struct PROC_HDR PROC_HDR
 

Enumerations

enum  ProcWaitStatus { PROC_WAIT_STATUS_OK , PROC_WAIT_STATUS_WAITING , PROC_WAIT_STATUS_ERROR }
 

Functions

int ProcGlobalSemas (void)
 
Size ProcGlobalShmemSize (void)
 
void InitProcGlobal (void)
 
void InitProcess (void)
 
void InitProcessPhase2 (void)
 
void InitAuxiliaryProcess (void)
 
void SetStartupBufferPinWaitBufId (int bufid)
 
int GetStartupBufferPinWaitBufId (void)
 
bool HaveNFreeProcs (int n, int *nfree)
 
void ProcReleaseLocks (bool isCommit)
 
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 LockErrorCleanup (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)
 
PGPROCAuxiliaryPidGetProc (int pid)
 
void BecomeLockGroupLeader (void)
 
bool BecomeLockGroupMember (PGPROC *leader, int pid)
 

Variables

PGDLLIMPORT int FastPathLockGroupsPerBackend
 
PGDLLIMPORT PGPROCMyProc
 
PGDLLIMPORT PROC_HDRProcGlobal
 
PGDLLIMPORT PGPROCPreparedXactProcs
 
PGDLLIMPORT int DeadlockTimeout
 
PGDLLIMPORT int StatementTimeout
 
PGDLLIMPORT int LockTimeout
 
PGDLLIMPORT int IdleInTransactionSessionTimeout
 
PGDLLIMPORT int TransactionTimeout
 
PGDLLIMPORT int IdleSessionTimeout
 
PGDLLIMPORT bool log_lock_waits
 

Macro Definition Documentation

◆ DELAY_CHKPT_COMPLETE

#define DELAY_CHKPT_COMPLETE   (1<<1)

Definition at line 121 of file proc.h.

◆ DELAY_CHKPT_START

#define DELAY_CHKPT_START   (1<<0)

Definition at line 120 of file proc.h.

◆ FastPathLockSlotsPerBackend

#define FastPathLockSlotsPerBackend ( )     (FP_LOCK_SLOTS_PER_GROUP * FastPathLockGroupsPerBackend)

Definition at line 85 of file proc.h.

◆ FP_LOCK_GROUPS_PER_BACKEND_MAX

#define FP_LOCK_GROUPS_PER_BACKEND_MAX   1024

Definition at line 83 of file proc.h.

◆ FP_LOCK_SLOTS_PER_GROUP

#define FP_LOCK_SLOTS_PER_GROUP   16 /* don't change */

Definition at line 84 of file proc.h.

◆ GetNumberFromPGProc

#define GetNumberFromPGProc (   proc)    ((proc) - &ProcGlobal->allProcs[0])

Definition at line 425 of file proc.h.

◆ GetPGProcByNumber

#define GetPGProcByNumber (   n)    (&ProcGlobal->allProcs[(n)])

Definition at line 424 of file proc.h.

◆ MAX_IO_WORKERS

#define MAX_IO_WORKERS   32

Definition at line 446 of file proc.h.

◆ NUM_AUXILIARY_PROCS

#define NUM_AUXILIARY_PROCS   (6 + MAX_IO_WORKERS)

Definition at line 447 of file proc.h.

◆ NUM_SPECIAL_WORKER_PROCS

#define NUM_SPECIAL_WORKER_PROCS   2

Definition at line 434 of file proc.h.

◆ PGPROC_MAX_CACHED_SUBXIDS

#define PGPROC_MAX_CACHED_SUBXIDS   64 /* XXX guessed-at value */

Definition at line 39 of file proc.h.

◆ PROC_AFFECTS_ALL_HORIZONS

#define PROC_AFFECTS_ALL_HORIZONS
Value:
0x20 /* this proc's xmin must be
* included in vacuum horizons
* in all databases */

Definition at line 62 of file proc.h.

◆ PROC_IN_LOGICAL_DECODING

#define PROC_IN_LOGICAL_DECODING
Value:
0x10 /* currently doing logical
* decoding outside xact */

Definition at line 61 of file proc.h.

◆ PROC_IN_SAFE_IC

#define PROC_IN_SAFE_IC
Value:
0x04 /* currently running CREATE INDEX
* CONCURRENTLY or REINDEX
* CONCURRENTLY on non-expressional,
* non-partial index */

Definition at line 59 of file proc.h.

◆ PROC_IN_VACUUM

#define PROC_IN_VACUUM   0x02 /* currently running lazy vacuum */

Definition at line 58 of file proc.h.

◆ PROC_IS_AUTOVACUUM

#define PROC_IS_AUTOVACUUM   0x01 /* is it an autovac worker? */

Definition at line 57 of file proc.h.

◆ PROC_VACUUM_FOR_WRAPAROUND

#define PROC_VACUUM_FOR_WRAPAROUND   0x08 /* set by autovac only */

Definition at line 60 of file proc.h.

◆ PROC_VACUUM_STATE_MASK

#define PROC_VACUUM_STATE_MASK    (PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND)

Definition at line 65 of file proc.h.

◆ PROC_XMIN_FLAGS

#define PROC_XMIN_FLAGS   (PROC_IN_VACUUM | PROC_IN_SAFE_IC)

Definition at line 72 of file proc.h.

Typedef Documentation

◆ PROC_HDR

typedef struct PROC_HDR PROC_HDR

◆ XidCacheStatus

Enumeration Type Documentation

◆ ProcWaitStatus

Enumerator
PROC_WAIT_STATUS_OK 
PROC_WAIT_STATUS_WAITING 
PROC_WAIT_STATUS_ERROR 

Definition at line 123 of file proc.h.

130{

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC * AuxiliaryPidGetProc ( int  pid)

Definition at line 1092 of file proc.c.

1093{
1094 PGPROC *result = NULL;
1095 int index;
1096
1097 if (pid == 0) /* never match dummy PGPROCs */
1098 return NULL;
1099
1100 for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1101 {
1102 PGPROC *proc = &AuxiliaryProcs[index];
1103
1104 if (proc->pid == pid)
1105 {
1106 result = proc;
1107 break;
1108 }
1109 }
1110 return result;
1111}
#define NUM_AUXILIARY_PROCS
Definition: proc.h:447
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:80
Definition: proc.h:163
int pid
Definition: proc.h:183
Definition: type.h:96

References AuxiliaryProcs, NUM_AUXILIARY_PROCS, and PGPROC::pid.

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

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 2002 of file proc.c.

2003{
2004 LWLock *leader_lwlock;
2005
2006 /* If we already did it, we don't need to do it again. */
2008 return;
2009
2010 /* We had better not be a follower. */
2011 Assert(MyProc->lockGroupLeader == NULL);
2012
2013 /* Create single-member group, containing only ourselves. */
2014 leader_lwlock = LockHashPartitionLockByProc(MyProc);
2015 LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
2018 LWLockRelease(leader_lwlock);
2019}
Assert(PointerIsAligned(start, uint64))
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:542
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1182
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1902
@ LW_EXCLUSIVE
Definition: lwlock.h:114
PGPROC * MyProc
Definition: proc.c:67
Definition: lwlock.h:42
dlist_head lockGroupMembers
Definition: proc.h:306
dlist_node lockGroupLink
Definition: proc.h:307
PGPROC * lockGroupLeader
Definition: proc.h:305

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

Referenced by LaunchParallelWorkers().

◆ BecomeLockGroupMember()

bool BecomeLockGroupMember ( PGPROC leader,
int  pid 
)

Definition at line 2032 of file proc.c.

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

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

Referenced by ParallelWorkerMain().

◆ CheckDeadLockAlert()

void CheckDeadLockAlert ( void  )

Definition at line 1874 of file proc.c.

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

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

1903{
1904 dlist_iter proc_iter;
1905 PROCLOCK *curproclock;
1906 LOCK *lock = locallock->lock;
1907 bool first_holder = true,
1908 first_waiter = true;
1909
1910#ifdef USE_ASSERT_CHECKING
1911 {
1912 uint32 hashcode = locallock->hashcode;
1913 LWLock *partitionLock = LockHashPartitionLock(hashcode);
1914
1915 Assert(LWLockHeldByMe(partitionLock));
1916 }
1917#endif
1918
1919 *lockHoldersNum = 0;
1920
1921 /*
1922 * Loop over the lock's procLocks to gather a list of all holders and
1923 * waiters. Thus we will be able to provide more detailed information for
1924 * lock debugging purposes.
1925 *
1926 * lock->procLocks contains all processes which hold or wait for this
1927 * lock.
1928 */
1929 dlist_foreach(proc_iter, &lock->procLocks)
1930 {
1931 curproclock =
1932 dlist_container(PROCLOCK, lockLink, proc_iter.cur);
1933
1934 /*
1935 * We are a waiter if myProc->waitProcLock == curproclock; we are a
1936 * holder if it is NULL or something different.
1937 */
1938 if (curproclock->tag.myProc->waitProcLock == curproclock)
1939 {
1940 if (first_waiter)
1941 {
1942 appendStringInfo(lock_waiters_sbuf, "%d",
1943 curproclock->tag.myProc->pid);
1944 first_waiter = false;
1945 }
1946 else
1947 appendStringInfo(lock_waiters_sbuf, ", %d",
1948 curproclock->tag.myProc->pid);
1949 }
1950 else
1951 {
1952 if (first_holder)
1953 {
1954 appendStringInfo(lock_holders_sbuf, "%d",
1955 curproclock->tag.myProc->pid);
1956 first_holder = false;
1957 }
1958 else
1959 appendStringInfo(lock_holders_sbuf, ", %d",
1960 curproclock->tag.myProc->pid);
1961
1962 (*lockHoldersNum)++;
1963 }
1964 }
1965}
uint32_t uint32
Definition: c.h:502
#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:527
bool LWLockHeldByMe(LWLock *lock)
Definition: lwlock.c:1970
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
uint32 hashcode
Definition: lock.h:433
LOCK * lock
Definition: lock.h:434
Definition: lock.h:310
dlist_head procLocks
Definition: lock.h:317
PROCLOCK * waitProcLock
Definition: proc.h:234
PGPROC * myProc
Definition: lock.h:367
Definition: lock.h:371
PROCLOCKTAG tag
Definition: lock.h:373
dlist_node * cur
Definition: ilist.h:179

References appendStringInfo(), Assert(), dlist_iter::cur, dlist_container, dlist_foreach, LOCALLOCK::hashcode, LOCALLOCK::lock, LockHashPartitionLock, LWLockHeldByMe(), PROCLOCKTAG::myProc, PGPROC::pid, LOCK::procLocks, PROCLOCK::tag, and PGPROC::waitProcLock.

Referenced by LockAcquireExtended(), and ProcSleep().

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 767 of file proc.c.

768{
769 /* use volatile pointer to prevent code rearrangement */
770 volatile PROC_HDR *procglobal = ProcGlobal;
771
772 return procglobal->startupBufferPinWaitBufId;
773}
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: proc.h:370
int startupBufferPinWaitBufId
Definition: proc.h:414

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and ProcessRecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int *  nfree 
)

Definition at line 783 of file proc.c.

784{
785 dlist_iter iter;
786
787 Assert(n > 0);
788 Assert(nfree);
789
791
792 *nfree = 0;
794 {
795 (*nfree)++;
796 if (*nfree == n)
797 break;
798 }
799
801
802 return (*nfree == n);
803}
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:76
dlist_head freeProcs
Definition: proc.h:392

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 616 of file proc.c.

617{
618 PGPROC *auxproc;
619 int proctype;
620
621 /*
622 * ProcGlobal should be set up already (if we are a backend, we inherit
623 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
624 */
625 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
626 elog(PANIC, "proc header uninitialized");
627
628 if (MyProc != NULL)
629 elog(ERROR, "you already exist");
630
633
634 /*
635 * We use the ProcStructLock to protect assignment and releasing of
636 * AuxiliaryProcs entries.
637 *
638 * While we are holding the ProcStructLock, also copy the current shared
639 * estimate of spins_per_delay to local storage.
640 */
642
644
645 /*
646 * Find a free auxproc ... *big* trouble if there isn't one ...
647 */
648 for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
649 {
650 auxproc = &AuxiliaryProcs[proctype];
651 if (auxproc->pid == 0)
652 break;
653 }
654 if (proctype >= NUM_AUXILIARY_PROCS)
655 {
657 elog(FATAL, "all AuxiliaryProcs are in use");
658 }
659
660 /* Mark auxiliary proc as in use by me */
661 /* use volatile pointer to prevent code rearrangement */
662 ((volatile PGPROC *) auxproc)->pid = MyProcPid;
663
665
666 MyProc = auxproc;
668
669 /*
670 * Initialize all fields of MyProc, except for those previously
671 * initialized by InitProcGlobal.
672 */
675 MyProc->fpVXIDLock = false;
684 MyProc->isRegularBackend = false;
686 MyProc->statusFlags = 0;
688 MyProc->lwWaitMode = 0;
689 MyProc->waitLock = NULL;
690 MyProc->waitProcLock = NULL;
692#ifdef USE_ASSERT_CHECKING
693 {
694 int i;
695
696 /* Last process should have released all locks. */
697 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
699 }
700#endif
701
702 /*
703 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
704 * on it. That allows us to repoint the process latch, which so far
705 * points to process local one, to the shared one.
706 */
709
710 /* now that we have a proc, report wait events to shared memory */
712
713 /* Check that group locking fields are in a proper initial state. */
714 Assert(MyProc->lockGroupLeader == NULL);
716
717 /*
718 * We might be reusing a semaphore that belonged to a failed process. So
719 * be careful and reinitialize its value here. (This is not strictly
720 * necessary anymore, but seems like a good idea for cleanliness.)
721 */
723
724 /*
725 * Arrange to clean up at process exit.
726 */
728
729 /*
730 * Now that we have a PGPROC, we could try to acquire lightweight locks.
731 * Initialize local state needed for them. (Heavyweight locks cannot be
732 * acquired in aux processes.)
733 */
735
736#ifdef EXEC_BACKEND
737
738 /*
739 * Initialize backend-local pointers to all the shared data structures.
740 * (We couldn't do this until now because it needs LWLocks.)
741 */
743 AttachSharedMemoryStructs();
744#endif
745}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:485
#define FATAL
Definition: elog.h:41
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
int MyProcPid
Definition: globals.c:48
ProcNumber MyProcNumber
Definition: globals.c:91
bool IsUnderPostmaster
Definition: globals.c:121
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:365
int i
Definition: isn.c:77
void OwnLatch(Latch *latch)
Definition: latch.c:126
#define InvalidLocalTransactionId
Definition: lock.h:66
void InitLWLockAccess(void)
Definition: lwlock.c:571
@ LW_WS_NOT_WAITING
Definition: lwlock.h:30
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:97
void SwitchToSharedLatch(void)
Definition: miscinit.c:215
void RegisterPostmasterChildActive(void)
Definition: pmsignal.c:290
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:294
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
#define InvalidOid
Definition: postgres_ext.h:35
#define GetNumberFromPGProc(proc)
Definition: proc.h:425
@ PROC_WAIT_STATUS_OK
Definition: proc.h:125
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
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:1041
bool isRegularBackend
Definition: proc.h:214
TransactionId xmin
Definition: proc.h:178
struct PGPROC::@127 vxid
LocalTransactionId lxid
Definition: proc.h:201
uint8 lwWaitMode
Definition: proc.h:225
uint32 wait_event_info
Definition: proc.h:280
uint8 statusFlags
Definition: proc.h:243
Oid databaseId
Definition: proc.h:208
pg_atomic_uint64 waitStart
Definition: proc.h:238
bool fpVXIDLock
Definition: proc.h:297
ProcNumber procNumber
Definition: proc.h:196
LOCK * waitLock
Definition: proc.h:233
TransactionId xid
Definition: proc.h:173
int delayChkptFlags
Definition: proc.h:241
LocalTransactionId fpLocalTransactionId
Definition: proc.h:298
PGSemaphore sem
Definition: proc.h:167
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:262
Oid roleId
Definition: proc.h:209
ProcWaitStatus waitStatus
Definition: proc.h:168
Oid tempNamespaceId
Definition: proc.h:211
dlist_node links
Definition: proc.h:164
uint8 lwWaiting
Definition: proc.h:224
Latch procLatch
Definition: proc.h:170
int spins_per_delay
Definition: proc.h:412
#define InvalidTransactionId
Definition: transam.h:31
void pgstat_set_wait_event_storage(uint32 *wait_event_info)
Definition: wait_event.c:349

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

Referenced by AuxiliaryProcessMainCommon().

◆ InitProcess()

void InitProcess ( void  )

Definition at line 391 of file proc.c.

392{
393 dlist_head *procgloballist;
394
395 /*
396 * ProcGlobal should be set up already (if we are a backend, we inherit
397 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
398 */
399 if (ProcGlobal == NULL)
400 elog(PANIC, "proc header uninitialized");
401
402 if (MyProc != NULL)
403 elog(ERROR, "you already exist");
404
405 /*
406 * Before we start accessing the shared memory in a serious way, mark
407 * ourselves as an active postmaster child; this is so that the postmaster
408 * can detect it if we exit without cleaning up.
409 */
412
413 /*
414 * Decide which list should supply our PGPROC. This logic must match the
415 * way the freelists were constructed in InitProcGlobal().
416 */
418 procgloballist = &ProcGlobal->autovacFreeProcs;
419 else if (AmBackgroundWorkerProcess())
420 procgloballist = &ProcGlobal->bgworkerFreeProcs;
421 else if (AmWalSenderProcess())
422 procgloballist = &ProcGlobal->walsenderFreeProcs;
423 else
424 procgloballist = &ProcGlobal->freeProcs;
425
426 /*
427 * Try to get a proc struct from the appropriate free list. If this
428 * fails, we must be out of PGPROC structures (not to mention semaphores).
429 *
430 * While we are holding the ProcStructLock, also copy the current shared
431 * estimate of spins_per_delay to local storage.
432 */
434
436
437 if (!dlist_is_empty(procgloballist))
438 {
441 }
442 else
443 {
444 /*
445 * If we reach here, all the PGPROCs are in use. This is one of the
446 * possible places to detect "too many backends", so give the standard
447 * error message. XXX do we need to give a different failure message
448 * in the autovacuum case?
449 */
451 if (AmWalSenderProcess())
453 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
454 errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
457 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
458 errmsg("sorry, too many clients already")));
459 }
461
462 /*
463 * Cross-check that the PGPROC is of the type we expect; if this were not
464 * the case, it would get returned to the wrong list.
465 */
466 Assert(MyProc->procgloballist == procgloballist);
467
468 /*
469 * Initialize all fields of MyProc, except for those previously
470 * initialized by InitProcGlobal.
471 */
474 MyProc->fpVXIDLock = false;
481 /* databaseId and roleId will be filled in later */
487 MyProc->statusFlags = 0;
488 /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
492 MyProc->lwWaitMode = 0;
493 MyProc->waitLock = NULL;
494 MyProc->waitProcLock = NULL;
496#ifdef USE_ASSERT_CHECKING
497 {
498 int i;
499
500 /* Last process should have released all locks. */
501 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
503 }
504#endif
506
507 /* Initialize fields for sync rep */
508 MyProc->waitLSN = 0;
511
512 /* Initialize fields for group XID clearing. */
516
517 /* Check that group locking fields are in a proper initial state. */
518 Assert(MyProc->lockGroupLeader == NULL);
520
521 /* Initialize wait event information. */
523
524 /* Initialize fields for group transaction status update. */
525 MyProc->clogGroupMember = false;
531
532 /*
533 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
534 * on it. That allows us to repoint the process latch, which so far
535 * points to process local one, to the shared one.
536 */
539
540 /* now that we have a proc, report wait events to shared memory */
542
543 /*
544 * We might be reusing a semaphore that belonged to a failed process. So
545 * be careful and reinitialize its value here. (This is not strictly
546 * necessary anymore, but seems like a good idea for cleanliness.)
547 */
549
550 /*
551 * Arrange to clean up at backend exit.
552 */
554
555 /*
556 * Now that we have a PGPROC, we could try to acquire locks, so initialize
557 * local state needed for LWLocks, and the deadlock checker.
558 */
561
562#ifdef EXEC_BACKEND
563
564 /*
565 * Initialize backend-local pointers to all the shared data structures.
566 * (We couldn't do this until now because it needs LWLocks.)
567 */
569 AttachSharedMemoryStructs();
570#endif
571}
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:239
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:27
void InitDeadLockChecking(void)
Definition: deadlock.c:144
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:149
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition: ilist.h:450
#define AmAutoVacuumWorkerProcess()
Definition: miscadmin.h:383
#define AmBackgroundWorkerProcess()
Definition: miscadmin.h:384
#define AmWalSenderProcess()
Definition: miscadmin.h:385
#define AmSpecialWorkerProcess()
Definition: miscadmin.h:396
#define AmRegularBackendProcess()
Definition: miscadmin.h:381
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
static void ProcKill(int code, Datum arg)
Definition: proc.c:920
bool procArrayGroupMember
Definition: proc.h:270
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:290
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:272
dlist_head * procgloballist
Definition: proc.h:165
bool recoveryConflictPending
Definition: proc.h:221
TransactionId clogGroupMemberXid
Definition: proc.h:285
int64 clogGroupMemberPage
Definition: proc.h:288
bool clogGroupMember
Definition: proc.h:283
XLogRecPtr waitLSN
Definition: proc.h:253
dlist_node syncRepLinks
Definition: proc.h:255
int syncRepState
Definition: proc.h:254
pg_atomic_uint32 clogGroupNext
Definition: proc.h:284
XidStatus clogGroupMemberXidStatus
Definition: proc.h:286
TransactionId procArrayGroupMemberXid
Definition: proc.h:278
dlist_head autovacFreeProcs
Definition: proc.h:394
dlist_head walsenderFreeProcs
Definition: proc.h:398
dlist_head bgworkerFreeProcs
Definition: proc.h:396
#define SYNC_REP_NOT_WAITING
Definition: syncrep.h:30
int max_wal_senders
Definition: walsender.c:126
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static struct link * links
Definition: zic.c:299

References AmAutoVacuumWorkerProcess, AmBackgroundWorkerProcess, AmRegularBackendProcess, AmSpecialWorkerProcess, AmWalSenderProcess, Assert(), PROC_HDR::autovacFreeProcs, 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, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, PROC_HDR::freeProcs, GetNumberFromPGProc, i, InitDeadLockChecking(), InitLWLockAccess(), INVALID_PROC_NUMBER, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, PGPROC::isRegularBackend, IsUnderPostmaster, PGPROC::links, links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LW_WS_NOT_WAITING, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, max_wal_senders, MyProc, PGPROC::myProcLocks, MyProcNumber, MyProcPid, NUM_LOCK_PARTITIONS, on_shmem_exit(), OwnLatch(), PANIC, pg_atomic_read_u32(), pg_atomic_write_u64(), PGSemaphoreReset(), pgstat_set_wait_event_storage(), PGPROC::pid, PROC_IS_AUTOVACUUM, PROC_WAIT_STATUS_OK, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::procgloballist, ProcKill(), PGPROC::procLatch, PGPROC::procNumber, ProcStructLock, PGPROC::recoveryConflictPending, RegisterPostmasterChildActive(), PGPROC::roleId, PGPROC::sem, set_spins_per_delay(), SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, PGPROC::statusFlags, SwitchToSharedLatch(), SYNC_REP_NOT_WAITING, PGPROC::syncRepLinks, PGPROC::syncRepState, PGPROC::tempNamespaceId, TRANSACTION_STATUS_IN_PROGRESS, PGPROC::vxid, PGPROC::wait_event_info, PGPROC::waitLock, PGPROC::waitLSN, PGPROC::waitProcLock, PGPROC::waitStart, PGPROC::waitStatus, PROC_HDR::walsenderFreeProcs, PGPROC::xid, and PGPROC::xmin.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackendMain(), BackgroundWorkerMain(), BootstrapModeMain(), PostgresSingleUserMain(), and ReplSlotSyncWorkerMain().

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 581 of file proc.c.

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

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 193 of file proc.c.

194{
195 PGPROC *procs;
196 int i,
197 j;
198 bool found;
200
201 /* Used for setup of per-backend fast-path slots. */
202 char *fpPtr,
203 *fpEndPtr PG_USED_FOR_ASSERTS_ONLY;
204 Size fpLockBitsSize,
205 fpRelIdSize;
206 Size requestSize;
207 char *ptr;
208
209 /* Create the ProcGlobal shared structure */
210 ProcGlobal = (PROC_HDR *)
211 ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
212 Assert(!found);
213
214 /*
215 * Initialize the data structures.
216 */
227
228 /*
229 * Create and initialize all the PGPROC structures we'll need. There are
230 * six separate consumers: (1) normal backends, (2) autovacuum workers and
231 * special workers, (3) background workers, (4) walsenders, (5) auxiliary
232 * processes, and (6) prepared transactions. (For largely-historical
233 * reasons, we combine autovacuum and special workers into one category
234 * with a single freelist.) Each PGPROC structure is dedicated to exactly
235 * one of these purposes, and they do not move between groups.
236 */
237 requestSize = PGProcShmemSize();
238
239 ptr = ShmemInitStruct("PGPROC structures",
240 requestSize,
241 &found);
242
243 MemSet(ptr, 0, requestSize);
244
245 procs = (PGPROC *) ptr;
246 ptr = (char *) ptr + TotalProcs * sizeof(PGPROC);
247
248 ProcGlobal->allProcs = procs;
249 /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
251
252 /*
253 * Allocate arrays mirroring PGPROC fields in a dense manner. See
254 * PROC_HDR.
255 *
256 * XXX: It might make sense to increase padding for these arrays, given
257 * how hotly they are accessed.
258 */
259 ProcGlobal->xids = (TransactionId *) ptr;
260 ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
261
263 ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
264
265 ProcGlobal->statusFlags = (uint8 *) ptr;
266 ptr = (char *) ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
267
268 /* make sure wer didn't overflow */
269 Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
270
271 /*
272 * Allocate arrays for fast-path locks. Those are variable-length, so
273 * can't be included in PGPROC directly. We allocate a separate piece of
274 * shared memory and then divide that between backends.
275 */
276 fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64));
277 fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid));
278
279 requestSize = FastPathLockShmemSize();
280
281 fpPtr = ShmemInitStruct("Fast-Path Lock Array",
282 requestSize,
283 &found);
284
285 MemSet(fpPtr, 0, requestSize);
286
287 /* For asserts checking we did not overflow. */
288 fpEndPtr = fpPtr + requestSize;
289
290 for (i = 0; i < TotalProcs; i++)
291 {
292 PGPROC *proc = &procs[i];
293
294 /* Common initialization for all PGPROCs, regardless of type. */
295
296 /*
297 * Set the fast-path lock arrays, and move the pointer. We interleave
298 * the two arrays, to (hopefully) get some locality for each backend.
299 */
300 proc->fpLockBits = (uint64 *) fpPtr;
301 fpPtr += fpLockBitsSize;
302
303 proc->fpRelId = (Oid *) fpPtr;
304 fpPtr += fpRelIdSize;
305
306 Assert(fpPtr <= fpEndPtr);
307
308 /*
309 * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
310 * dummy PGPROCs don't need these though - they're never associated
311 * with a real process
312 */
314 {
315 proc->sem = PGSemaphoreCreate();
316 InitSharedLatch(&(proc->procLatch));
318 }
319
320 /*
321 * Newly created PGPROCs for normal backends, autovacuum workers,
322 * special workers, bgworkers, and walsenders must be queued up on the
323 * appropriate free list. Because there can only ever be a small,
324 * fixed number of auxiliary processes, no free list is used in that
325 * case; InitAuxiliaryProcess() instead uses a linear search. PGPROCs
326 * for prepared transactions are added to a free list by
327 * TwoPhaseShmemInit().
328 */
329 if (i < MaxConnections)
330 {
331 /* PGPROC for normal backend, add to freeProcs list */
334 }
336 {
337 /* PGPROC for AV or special worker, add to autovacFreeProcs list */
340 }
342 {
343 /* PGPROC for bgworker, add to bgworkerFreeProcs list */
346 }
347 else if (i < MaxBackends)
348 {
349 /* PGPROC for walsender, add to walsenderFreeProcs list */
352 }
353
354 /* Initialize myProcLocks[] shared memory queues. */
355 for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
356 dlist_init(&(proc->myProcLocks[j]));
357
358 /* Initialize lockGroupMembers list. */
360
361 /*
362 * Initialize the atomic variables, otherwise, it won't be safe to
363 * access them for backends that aren't currently in use.
364 */
367 pg_atomic_init_u64(&(proc->waitStart), 0);
368 }
369
370 /* Should have consumed exactly the expected amount of fast-path memory. */
371 Assert(fpPtr == fpEndPtr);
372
373 /*
374 * Save pointers to the blocks of PGPROC structures reserved for auxiliary
375 * processes and prepared transactions.
376 */
377 AuxiliaryProcs = &procs[MaxBackends];
379
380 /* Create ProcStructLock spinlock, too */
381 ProcStructLock = (slock_t *) ShmemInitStruct("ProcStructLock spinlock",
382 sizeof(slock_t),
383 &found);
385}
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:221
static void pg_atomic_init_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:453
int autovacuum_worker_slots
Definition: autovacuum.c:119
#define MAXALIGN(LEN)
Definition: c.h:782
uint8_t uint8
Definition: c.h:500
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:224
uint64_t uint64
Definition: c.h:503
#define MemSet(start, val, len)
Definition: c.h:991
uint32 TransactionId
Definition: c.h:623
size_t Size
Definition: c.h:576
int MaxConnections
Definition: globals.c:144
int MaxBackends
Definition: globals.c:147
int max_worker_processes
Definition: globals.c:145
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
int FastPathLockGroupsPerBackend
Definition: lock.c:202
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:721
@ LWTRANCHE_LOCK_FASTPATH
Definition: lwlock.h:192
PGSemaphore PGSemaphoreCreate(void)
Definition: posix_sema.c:261
unsigned int Oid
Definition: postgres_ext.h:30
#define FastPathLockSlotsPerBackend()
Definition: proc.h:85
#define NUM_SPECIAL_WORKER_PROCS
Definition: proc.h:434
#define DEFAULT_SPINS_PER_DELAY
Definition: s_lock.h:720
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
#define SpinLockInit(lock)
Definition: spin.h:57
PGPROC * PreparedXactProcs
Definition: proc.c:81
static Size PGProcShmemSize(void)
Definition: proc.c:98
static Size FastPathLockShmemSize(void)
Definition: proc.c:116
LWLock fpInfoLock
Definition: proc.h:294
Oid * fpRelId
Definition: proc.h:296
uint64 * fpLockBits
Definition: proc.h:295
uint8 * statusFlags
Definition: proc.h:387
XidCacheStatus * subxidStates
Definition: proc.h:381
ProcNumber checkpointerProc
Definition: proc.h:409
PGPROC * allProcs
Definition: proc.h:372
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:402
TransactionId * xids
Definition: proc.h:375
ProcNumber walwriterProc
Definition: proc.h:408
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:400
uint32 allProcCount
Definition: proc.h:390
int max_prepared_xacts
Definition: twophase.c:115

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

Referenced by CreateOrAttachShmemStructs().

◆ JoinWaitQueue()

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

Definition at line 1141 of file proc.c.

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

References Assert(), LockMethodData::conflictTab, dlist_iter::cur, dclist_foreach, dclist_insert_before(), dclist_is_empty(), dclist_push_tail(), dlist_container, dlist_foreach, GrantLock(), PROCLOCK::groupLeader, LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, PGPROC::links, links, LOCALLOCK::lock, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, LW_EXCLUSIVE, LWLockHeldByMeInMode(), LOCALLOCKTAG::mode, MyProc, PG_USED_FOR_ASSERTS_ONLY, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_OK, PROC_WAIT_STATUS_WAITING, LOCALLOCK::proclock, LOCK::procLocks, RememberSimpleDeadLock(), LOCALLOCK::tag, PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, and PGPROC::waitStatus.

Referenced by LockAcquireExtended().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 814 of file proc.c.

815{
816 LOCALLOCK *lockAwaited;
817 LWLock *partitionLock;
818 DisableTimeoutParams timeouts[2];
819
821
823
824 /* Nothing to do if we weren't waiting for a lock */
825 lockAwaited = GetAwaitedLock();
826 if (lockAwaited == NULL)
827 {
829 return;
830 }
831
832 /*
833 * Turn off the deadlock and lock timeout timers, if they are still
834 * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
835 * indicator flag, since this function is executed before
836 * ProcessInterrupts when responding to SIGINT; else we'd lose the
837 * knowledge that the SIGINT came from a lock timeout and not an external
838 * source.
839 */
840 timeouts[0].id = DEADLOCK_TIMEOUT;
841 timeouts[0].keep_indicator = false;
842 timeouts[1].id = LOCK_TIMEOUT;
843 timeouts[1].keep_indicator = true;
844 disable_timeouts(timeouts, 2);
845
846 /* Unlink myself from the wait queue, if on it (might not be anymore!) */
847 partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
848 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
849
851 {
852 /* We could not have been granted the lock yet */
853 RemoveFromWaitQueue(MyProc, lockAwaited->hashcode);
854 }
855 else
856 {
857 /*
858 * Somebody kicked us off the lock queue already. Perhaps they
859 * granted us the lock, or perhaps they detected a deadlock. If they
860 * did grant us the lock, we'd better remember it in our local lock
861 * table.
862 */
865 }
866
868
869 LWLockRelease(partitionLock);
870
872}
static bool dlist_node_is_detached(const dlist_node *node)
Definition: ilist.h:525
void GrantAwaitedLock(void)
Definition: lock.c:1885
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:2011
void ResetAwaitedLock(void)
Definition: lock.c:1903
void AbortStrongLockAcquire(void)
Definition: lock.c:1856
LOCALLOCK * GetAwaitedLock(void)
Definition: lock.c:1894
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:136
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:134
TimeoutId id
Definition: timeout.h:71
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(), GetAwaitedLock(), GrantAwaitedLock(), LOCALLOCK::hashcode, HOLD_INTERRUPTS, DisableTimeoutParams::id, DisableTimeoutParams::keep_indicator, PGPROC::links, LOCK_TIMEOUT, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), ResetAwaitedLock(), RESUME_INTERRUPTS, and PGPROC::waitStatus.

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

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 158 of file proc.c.

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

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 140 of file proc.c.

141{
142 Size size = 0;
143
144 /* ProcGlobal */
145 size = add_size(size, sizeof(PROC_HDR));
146 size = add_size(size, sizeof(slock_t));
147
148 size = add_size(size, PGProcShmemSize());
149 size = add_size(size, FastPathLockShmemSize());
150
151 return size;
152}
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

References add_size(), FastPathLockShmemSize(), and PGProcShmemSize().

Referenced by CalculateShmemSize().

◆ ProcLockWakeup()

void ProcLockWakeup ( LockMethod  lockMethodTable,
LOCK lock 
)

Definition at line 1740 of file proc.c.

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

References LockMethodData::conflictTab, dlist_mutable_iter::cur, dclist_foreach_modify, dclist_is_empty(), dlist_container, GrantLock(), links, LOCKBIT_ON, LockCheckConflicts(), PROC_WAIT_STATUS_OK, ProcWakeup(), PGPROC::waitLockMode, PGPROC::waitProcLock, and LOCK::waitProcs.

Referenced by CleanUpLock(), and DeadLockCheck().

◆ ProcReleaseLocks()

void ProcReleaseLocks ( bool  isCommit)

Definition at line 892 of file proc.c.

893{
894 if (!MyProc)
895 return;
896 /* If waiting, get off wait queue (should only be needed after error) */
898 /* Release standard locks, including session-level if aborting */
900 /* Release transaction-level advisory locks */
902}
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2272
#define DEFAULT_LOCKMETHOD
Definition: lock.h:126
#define USER_LOCKMETHOD
Definition: lock.h:127
void LockErrorCleanup(void)
Definition: proc.c:814

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 1987 of file proc.c.

1988{
1989 if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
1990 elog(ERROR, "procNumber out of range");
1991
1992 SetLatch(&ProcGlobal->allProcs[procNumber].procLatch);
1993}

References PROC_HDR::allProcCount, PROC_HDR::allProcs, elog, ERROR, ProcGlobal, PGPROC::procLatch, and SetLatch().

Referenced by ReleasePredicateLocks(), and WakePinCountWaiter().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock)

Definition at line 1310 of file proc.c.

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

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

Referenced by WaitOnLock().

◆ ProcWaitForSignal()

void ProcWaitForSignal ( uint32  wait_event_info)

◆ ProcWakeup()

void ProcWakeup ( PGPROC proc,
ProcWaitStatus  waitStatus 
)

Definition at line 1712 of file proc.c.

1713{
1714 if (dlist_node_is_detached(&proc->links))
1715 return;
1716
1718
1719 /* Remove process from wait queue */
1721
1722 /* Clean up process' state and pass it the ok/fail signal */
1723 proc->waitLock = NULL;
1724 proc->waitProcLock = NULL;
1725 proc->waitStatus = waitStatus;
1727
1728 /* And awaken it */
1729 SetLatch(&proc->procLatch);
1730}
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(), PGPROC::links, MyProc, pg_atomic_write_u64(), PROC_WAIT_STATUS_WAITING, PGPROC::procLatch, SetLatch(), PGPROC::waitLock, PGPROC::waitProcLock, LOCK::waitProcs, PGPROC::waitStart, and PGPROC::waitStatus.

Referenced by ProcLockWakeup().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 755 of file proc.c.

756{
757 /* use volatile pointer to prevent code rearrangement */
758 volatile PROC_HDR *procglobal = ProcGlobal;
759
760 procglobal->startupBufferPinWaitBufId = bufid;
761}

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

Variable Documentation

◆ DeadlockTimeout

◆ FastPathLockGroupsPerBackend

PGDLLIMPORT int FastPathLockGroupsPerBackend
extern

◆ IdleInTransactionSessionTimeout

PGDLLIMPORT int IdleInTransactionSessionTimeout
extern

Definition at line 61 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

PGDLLIMPORT int IdleSessionTimeout
extern

Definition at line 63 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

PGDLLIMPORT int LockTimeout
extern

Definition at line 60 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

PGDLLIMPORT bool log_lock_waits
extern

Definition at line 64 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGDLLIMPORT PGPROC* MyProc
extern

Definition at line 67 of file proc.c.

Referenced by _brin_parallel_build_main(), _bt_parallel_build_main(), _gin_parallel_build_main(), AbortTransaction(), AtEOSubXact_Namespace(), AtEOXact_Namespace(), AtEOXact_Snapshot(), attach_to_queues(), AutoVacWorkerMain(), AuxiliaryProcKill(), BaseInit(), BecomeLockGroupLeader(), BecomeLockGroupMember(), CheckDeadLock(), CommitTransaction(), ComputeXidHorizons(), ConditionVariableBroadcast(), consume_xids_common(), CountOtherDBBackends(), CreateReplicationSlot(), DefineIndex(), EndPrepare(), errdetail_abort(), exec_eval_simple_expr(), exec_simple_check_plan(), exec_stmt_call(), ExecParallelGetReceiver(), ExecParallelSetupTupleQueues(), ExportSnapshot(), FastPathGetRelationLockEntry(), FastPathGrantRelationLock(), FastPathUnGrantRelationLock(), FindLockCycleRecurseMember(), get_cast_hashentry(), GetCurrentVirtualXIDs(), GetLockConflicts(), GetNewTransactionId(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), GetSnapshotDataReuse(), GetStableLatestTransactionId(), heap_inplace_update_and_unlock(), InitAuxiliaryProcess(), InitBufferManagerAccess(), InitializeParallelDSM(), InitPostgres(), InitProcess(), InitProcessPhase2(), InitRecoveryTransactionEnvironment(), InitTempTableNamespace(), InitWalSender(), JoinWaitQueue(), lock_and_open_sequence(), LockAcquireExtended(), LockCheckConflicts(), LockErrorCleanup(), LockRelease(), LockReleaseAll(), log_status_format(), logicalrep_worker_attach(), LWLockAcquire(), LWLockAcquireOrWait(), LWLockAttemptLock(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockWaitForVar(), MarkAsPreparingGuts(), MarkBufferDirtyHint(), MinimumActiveBackends(), pa_setup_dsm(), parallel_vacuum_main(), ParallelApplyWorkerMain(), ParallelWorkerMain(), pg_truncate_visibility_map(), pgaio_init_backend(), pgstat_report_activity(), PhysicalReplicationSlotNewXmin(), PostPrepare_Locks(), PrepareTransaction(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcessRecoveryConflictInterrupt(), ProcessStandbyHSFeedbackMessage(), ProcKill(), ProcReleaseLocks(), ProcSleep(), ProcWakeup(), RecordTransactionCommit(), RecordTransactionCommitPrepared(), ReinitializeParallelDSM(), RelationTruncate(), RemoveProcFromArray(), ReplicationSlotRelease(), ResolveRecoveryConflictWithLock(), set_indexsafe_procflags(), SetAuthenticatedUserId(), setup_dynamic_shared_memory(), shm_mq_attach(), shm_mq_detach_internal(), shm_mq_receive(), shm_mq_sendv(), shm_mq_wait_for_attach(), smgr_bulk_finish(), SnapBuildInitialSnapshot(), SnapshotResetXmin(), StartTransaction(), StartupDecodingContext(), SwitchBackToLocalLatch(), SwitchToSharedLatch(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepQueueInsert(), SyncRepWaitForLSN(), TerminateOtherDBBackends(), TransactionGroupUpdateXidStatus(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), TruncateMultiXact(), vacuum_rel(), validate_sync_standby_slots(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), WaitXLogInsertionsToFinish(), write_csvlog(), write_jsonlog(), XidCacheRemoveRunningXids(), and XLogSaveBufferForHint().

◆ PreparedXactProcs

PGDLLIMPORT PGPROC* PreparedXactProcs
extern

Definition at line 81 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ StatementTimeout

PGDLLIMPORT int StatementTimeout
extern

Definition at line 59 of file proc.c.

Referenced by enable_statement_timeout().

◆ TransactionTimeout