Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
PostgreSQL Source Code git master
#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 129 of file proc.h.

◆ DELAY_CHKPT_START

#define DELAY_CHKPT_START   (1<<0)

Definition at line 128 of file proc.h.

◆ FastPathLockSlotsPerBackend

#define FastPathLockSlotsPerBackend ( )     (FP_LOCK_SLOTS_PER_GROUP * FastPathLockGroupsPerBackend)

Definition at line 93 of file proc.h.

◆ FP_LOCK_GROUPS_PER_BACKEND_MAX

#define FP_LOCK_GROUPS_PER_BACKEND_MAX   1024

Definition at line 91 of file proc.h.

◆ FP_LOCK_SLOTS_PER_GROUP

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

Definition at line 92 of file proc.h.

◆ GetNumberFromPGProc

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

Definition at line 433 of file proc.h.

◆ GetPGProcByNumber

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

Definition at line 432 of file proc.h.

◆ MAX_IO_WORKERS

#define MAX_IO_WORKERS   32

Definition at line 454 of file proc.h.

◆ NUM_AUXILIARY_PROCS

#define NUM_AUXILIARY_PROCS   (6 + MAX_IO_WORKERS)

Definition at line 455 of file proc.h.

◆ NUM_SPECIAL_WORKER_PROCS

#define NUM_SPECIAL_WORKER_PROCS   2

Definition at line 442 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 131 of file proc.h.

138{

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC * AuxiliaryPidGetProc ( int  pid)

Definition at line 1091 of file proc.c.

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

References AuxiliaryProcs, NUM_AUXILIARY_PROCS, and PGPROC::pid.

Referenced by 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 2001 of file proc.c.

2002{
2003 LWLock *leader_lwlock;
2004
2005 /* If we already did it, we don't need to do it again. */
2007 return;
2008
2009 /* We had better not be a follower. */
2010 Assert(MyProc->lockGroupLeader == NULL);
2011
2012 /* Create single-member group, containing only ourselves. */
2013 leader_lwlock = LockHashPartitionLockByProc(MyProc);
2014 LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
2017 LWLockRelease(leader_lwlock);
2018}
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:1180
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1900
@ LW_EXCLUSIVE
Definition: lwlock.h:114
PGPROC * MyProc
Definition: proc.c:66
Definition: lwlock.h:42
dlist_head lockGroupMembers
Definition: proc.h:314
dlist_node lockGroupLink
Definition: proc.h:315
PGPROC * lockGroupLeader
Definition: proc.h:313

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

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

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

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

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

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

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and ProcessRecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int *  nfree 
)

Definition at line 782 of file proc.c.

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

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 615 of file proc.c.

616{
617 PGPROC *auxproc;
618 int proctype;
619
620 /*
621 * ProcGlobal should be set up already (if we are a backend, we inherit
622 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
623 */
624 if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
625 elog(PANIC, "proc header uninitialized");
626
627 if (MyProc != NULL)
628 elog(ERROR, "you already exist");
629
632
633 /*
634 * We use the ProcStructLock to protect assignment and releasing of
635 * AuxiliaryProcs entries.
636 *
637 * While we are holding the ProcStructLock, also copy the current shared
638 * estimate of spins_per_delay to local storage.
639 */
641
643
644 /*
645 * Find a free auxproc ... *big* trouble if there isn't one ...
646 */
647 for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
648 {
649 auxproc = &AuxiliaryProcs[proctype];
650 if (auxproc->pid == 0)
651 break;
652 }
653 if (proctype >= NUM_AUXILIARY_PROCS)
654 {
656 elog(FATAL, "all AuxiliaryProcs are in use");
657 }
658
659 /* Mark auxiliary proc as in use by me */
660 /* use volatile pointer to prevent code rearrangement */
661 ((volatile PGPROC *) auxproc)->pid = MyProcPid;
662
664
665 MyProc = auxproc;
667
668 /*
669 * Initialize all fields of MyProc, except for those previously
670 * initialized by InitProcGlobal.
671 */
674 MyProc->fpVXIDLock = false;
683 MyProc->isRegularBackend = false;
685 MyProc->statusFlags = 0;
687 MyProc->lwWaitMode = 0;
688 MyProc->waitLock = NULL;
689 MyProc->waitProcLock = NULL;
691#ifdef USE_ASSERT_CHECKING
692 {
693 int i;
694
695 /* Last process should have released all locks. */
696 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
698 }
699#endif
700
701 /*
702 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
703 * on it. That allows us to repoint the process latch, which so far
704 * points to process local one, to the shared one.
705 */
708
709 /* now that we have a proc, report wait events to shared memory */
711
712 /* Check that group locking fields are in a proper initial state. */
713 Assert(MyProc->lockGroupLeader == NULL);
715
716 /*
717 * We might be reusing a semaphore that belonged to a failed process. So
718 * be careful and reinitialize its value here. (This is not strictly
719 * necessary anymore, but seems like a good idea for cleanliness.)
720 */
722
723 /*
724 * Arrange to clean up at process exit.
725 */
727
728 /*
729 * Now that we have a PGPROC, we could try to acquire lightweight locks.
730 * Initialize local state needed for them. (Heavyweight locks cannot be
731 * acquired in aux processes.)
732 */
734
735#ifdef EXEC_BACKEND
736
737 /*
738 * Initialize backend-local pointers to all the shared data structures.
739 * (We couldn't do this until now because it needs LWLocks.)
740 */
742 AttachSharedMemoryStructs();
743#endif
744}
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:225
int MyProcPid
Definition: globals.c:47
ProcNumber MyProcNumber
Definition: globals.c:90
bool IsUnderPostmaster
Definition: globals.c:120
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
static void dlist_node_init(dlist_node *node)
Definition: ilist.h:325
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c: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:569
@ 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:433
@ PROC_WAIT_STATUS_OK
Definition: proc.h:133
#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:1040
bool isRegularBackend
Definition: proc.h:222
TransactionId xmin
Definition: proc.h:186
struct PGPROC::@127 vxid
LocalTransactionId lxid
Definition: proc.h:209
uint8 lwWaitMode
Definition: proc.h:233
uint32 wait_event_info
Definition: proc.h:288
uint8 statusFlags
Definition: proc.h:251
Oid databaseId
Definition: proc.h:216
pg_atomic_uint64 waitStart
Definition: proc.h:246
bool fpVXIDLock
Definition: proc.h:305
ProcNumber procNumber
Definition: proc.h:204
LOCK * waitLock
Definition: proc.h:241
TransactionId xid
Definition: proc.h:181
int delayChkptFlags
Definition: proc.h:249
LocalTransactionId fpLocalTransactionId
Definition: proc.h:306
PGSemaphore sem
Definition: proc.h:175
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:270
Oid roleId
Definition: proc.h:217
ProcWaitStatus waitStatus
Definition: proc.h:176
Oid tempNamespaceId
Definition: proc.h:219
dlist_node links
Definition: proc.h:172
uint8 lwWaiting
Definition: proc.h:232
Latch procLatch
Definition: proc.h:178
int spins_per_delay
Definition: proc.h:420
#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 390 of file proc.c.

391{
392 dlist_head *procgloballist;
393
394 /*
395 * ProcGlobal should be set up already (if we are a backend, we inherit
396 * this by fork() or EXEC_BACKEND mechanism from the postmaster).
397 */
398 if (ProcGlobal == NULL)
399 elog(PANIC, "proc header uninitialized");
400
401 if (MyProc != NULL)
402 elog(ERROR, "you already exist");
403
404 /*
405 * Before we start accessing the shared memory in a serious way, mark
406 * ourselves as an active postmaster child; this is so that the postmaster
407 * can detect it if we exit without cleaning up.
408 */
411
412 /*
413 * Decide which list should supply our PGPROC. This logic must match the
414 * way the freelists were constructed in InitProcGlobal().
415 */
417 procgloballist = &ProcGlobal->autovacFreeProcs;
418 else if (AmBackgroundWorkerProcess())
419 procgloballist = &ProcGlobal->bgworkerFreeProcs;
420 else if (AmWalSenderProcess())
421 procgloballist = &ProcGlobal->walsenderFreeProcs;
422 else
423 procgloballist = &ProcGlobal->freeProcs;
424
425 /*
426 * Try to get a proc struct from the appropriate free list. If this
427 * fails, we must be out of PGPROC structures (not to mention semaphores).
428 *
429 * While we are holding the ProcStructLock, also copy the current shared
430 * estimate of spins_per_delay to local storage.
431 */
433
435
436 if (!dlist_is_empty(procgloballist))
437 {
440 }
441 else
442 {
443 /*
444 * If we reach here, all the PGPROCs are in use. This is one of the
445 * possible places to detect "too many backends", so give the standard
446 * error message. XXX do we need to give a different failure message
447 * in the autovacuum case?
448 */
450 if (AmWalSenderProcess())
452 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
453 errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
456 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
457 errmsg("sorry, too many clients already")));
458 }
460
461 /*
462 * Cross-check that the PGPROC is of the type we expect; if this were not
463 * the case, it would get returned to the wrong list.
464 */
465 Assert(MyProc->procgloballist == procgloballist);
466
467 /*
468 * Initialize all fields of MyProc, except for those previously
469 * initialized by InitProcGlobal.
470 */
473 MyProc->fpVXIDLock = false;
480 /* databaseId and roleId will be filled in later */
486 MyProc->statusFlags = 0;
487 /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
491 MyProc->lwWaitMode = 0;
492 MyProc->waitLock = NULL;
493 MyProc->waitProcLock = NULL;
495#ifdef USE_ASSERT_CHECKING
496 {
497 int i;
498
499 /* Last process should have released all locks. */
500 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
502 }
503#endif
505
506 /* Initialize fields for sync rep */
507 MyProc->waitLSN = 0;
510
511 /* Initialize fields for group XID clearing. */
515
516 /* Check that group locking fields are in a proper initial state. */
517 Assert(MyProc->lockGroupLeader == NULL);
519
520 /* Initialize wait event information. */
522
523 /* Initialize fields for group transaction status update. */
524 MyProc->clogGroupMember = false;
530
531 /*
532 * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
533 * on it. That allows us to repoint the process latch, which so far
534 * points to process local one, to the shared one.
535 */
538
539 /* now that we have a proc, report wait events to shared memory */
541
542 /*
543 * We might be reusing a semaphore that belonged to a failed process. So
544 * be careful and reinitialize its value here. (This is not strictly
545 * necessary anymore, but seems like a good idea for cleanliness.)
546 */
548
549 /*
550 * Arrange to clean up at backend exit.
551 */
553
554 /*
555 * Now that we have a PGPROC, we could try to acquire locks, so initialize
556 * local state needed for LWLocks, and the deadlock checker.
557 */
560
561#ifdef EXEC_BACKEND
562
563 /*
564 * Initialize backend-local pointers to all the shared data structures.
565 * (We couldn't do this until now because it needs LWLocks.)
566 */
568 AttachSharedMemoryStructs();
569#endif
570}
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:382
#define AmBackgroundWorkerProcess()
Definition: miscadmin.h:383
#define AmWalSenderProcess()
Definition: miscadmin.h:384
#define AmSpecialWorkerProcess()
Definition: miscadmin.h:395
#define AmRegularBackendProcess()
Definition: miscadmin.h:380
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
static void ProcKill(int code, Datum arg)
Definition: proc.c:919
bool procArrayGroupMember
Definition: proc.h:278
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:298
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:280
dlist_head * procgloballist
Definition: proc.h:173
bool recoveryConflictPending
Definition: proc.h:229
TransactionId clogGroupMemberXid
Definition: proc.h:293
int64 clogGroupMemberPage
Definition: proc.h:296
bool clogGroupMember
Definition: proc.h:291
XLogRecPtr waitLSN
Definition: proc.h:261
dlist_node syncRepLinks
Definition: proc.h:263
int syncRepState
Definition: proc.h:262
pg_atomic_uint32 clogGroupNext
Definition: proc.h:292
XidStatus clogGroupMemberXidStatus
Definition: proc.h:294
TransactionId procArrayGroupMemberXid
Definition: proc.h:286
dlist_head autovacFreeProcs
Definition: proc.h:402
dlist_head walsenderFreeProcs
Definition: proc.h:406
dlist_head bgworkerFreeProcs
Definition: proc.h:404
#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 580 of file proc.c.

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

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 192 of file proc.c.

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

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

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

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

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 139 of file proc.c.

140{
141 Size size = 0;
142
143 /* ProcGlobal */
144 size = add_size(size, sizeof(PROC_HDR));
145 size = add_size(size, sizeof(slock_t));
146
147 size = add_size(size, PGProcShmemSize());
148 size = add_size(size, FastPathLockShmemSize());
149
150 return size;
151}
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 1739 of file proc.c.

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

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

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 1986 of file proc.c.

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

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

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

1712{
1713 if (dlist_node_is_detached(&proc->links))
1714 return;
1715
1717
1718 /* Remove process from wait queue */
1720
1721 /* Clean up process' state and pass it the ok/fail signal */
1722 proc->waitLock = NULL;
1723 proc->waitProcLock = NULL;
1724 proc->waitStatus = waitStatus;
1726
1727 /* And awaken it */
1728 SetLatch(&proc->procLatch);
1729}
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 754 of file proc.c.

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

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

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

PGDLLIMPORT int IdleSessionTimeout
extern

Definition at line 62 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

PGDLLIMPORT int LockTimeout
extern

Definition at line 59 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

PGDLLIMPORT bool log_lock_waits
extern

Definition at line 63 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGDLLIMPORT PGPROC* MyProc
extern

Definition at line 66 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 80 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ StatementTimeout

PGDLLIMPORT int StatementTimeout
extern

Definition at line 58 of file proc.c.

Referenced by enable_statement_timeout().

◆ TransactionTimeout