PostgreSQL Source Code  git master
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_SLOTS_PER_BACKEND   16
 
#define DELAY_CHKPT_START   (1<<0)
 
#define DELAY_CHKPT_COMPLETE   (1<<1)
 
#define ProcNumberForTempRelations()    (ParallelLeaderProcNumber == INVALID_PROC_NUMBER ? MyProcNumber : ParallelLeaderProcNumber)
 
#define GetPGProcByNumber(n)   (&ProcGlobal->allProcs[(n)])
 
#define GetNumberFromPGProc(proc)   ((proc) - &ProcGlobal->allProcs[0])
 
#define NUM_AUXILIARY_PROCS   6
 

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 ProcSleep (LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait)
 
void ProcWakeup (PGPROC *proc, ProcWaitStatus waitStatus)
 
void ProcLockWakeup (LockMethod lockMethodTable, LOCK *lock)
 
void CheckDeadLockAlert (void)
 
bool IsWaitingForLock (void)
 
void LockErrorCleanup (void)
 
void ProcWaitForSignal (uint32 wait_event_info)
 
void ProcSendSignal (ProcNumber procNumber)
 
PGPROCAuxiliaryPidGetProc (int pid)
 
void BecomeLockGroupLeader (void)
 
bool BecomeLockGroupMember (PGPROC *leader, int pid)
 

Variables

PGDLLIMPORT PGPROCMyProc
 
PGDLLIMPORT ProcNumber MyProcNumber
 
PGDLLIMPORT ProcNumber ParallelLeaderProcNumber
 
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 115 of file proc.h.

◆ DELAY_CHKPT_START

#define DELAY_CHKPT_START   (1<<0)

Definition at line 114 of file proc.h.

◆ FP_LOCK_SLOTS_PER_BACKEND

#define FP_LOCK_SLOTS_PER_BACKEND   16

Definition at line 80 of file proc.h.

◆ GetNumberFromPGProc

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

Definition at line 428 of file proc.h.

◆ GetPGProcByNumber

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

Definition at line 427 of file proc.h.

◆ NUM_AUXILIARY_PROCS

#define NUM_AUXILIARY_PROCS   6

Definition at line 439 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.

◆ ProcNumberForTempRelations

#define ProcNumberForTempRelations ( )     (ParallelLeaderProcNumber == INVALID_PROC_NUMBER ? MyProcNumber : ParallelLeaderProcNumber)

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

124 {

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC* AuxiliaryPidGetProc ( int  pid)

Definition at line 1024 of file proc.c.

1025 {
1026  PGPROC *result = NULL;
1027  int index;
1028 
1029  if (pid == 0) /* never match dummy PGPROCs */
1030  return NULL;
1031 
1032  for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1033  {
1034  PGPROC *proc = &AuxiliaryProcs[index];
1035 
1036  if (proc->pid == pid)
1037  {
1038  result = proc;
1039  break;
1040  }
1041  }
1042  return result;
1043 }
#define NUM_AUXILIARY_PROCS
Definition: proc.h:439
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:80
Definition: proc.h:157
int pid
Definition: proc.h:177
Definition: type.h:95

References AuxiliaryProcs, NUM_AUXILIARY_PROCS, and PGPROC::pid.

Referenced by pg_log_backend_memory_contexts(), and pg_stat_get_activity().

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 1899 of file proc.c.

1900 {
1901  LWLock *leader_lwlock;
1902 
1903  /* If we already did it, we don't need to do it again. */
1904  if (MyProc->lockGroupLeader == MyProc)
1905  return;
1906 
1907  /* We had better not be a follower. */
1908  Assert(MyProc->lockGroupLeader == NULL);
1909 
1910  /* Create single-member group, containing only ourselves. */
1911  leader_lwlock = LockHashPartitionLockByProc(MyProc);
1912  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1915  LWLockRelease(leader_lwlock);
1916 }
#define Assert(condition)
Definition: c.h:858
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:541
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:114
PGPROC * MyProc
Definition: proc.c:67
Definition: lwlock.h:42
dlist_head lockGroupMembers
Definition: proc.h:300
dlist_node lockGroupLink
Definition: proc.h:301
PGPROC * lockGroupLeader
Definition: proc.h:299

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

1930 {
1931  LWLock *leader_lwlock;
1932  bool ok = false;
1933 
1934  /* Group leader can't become member of group */
1935  Assert(MyProc != leader);
1936 
1937  /* Can't already be a member of a group */
1938  Assert(MyProc->lockGroupLeader == NULL);
1939 
1940  /* PID must be valid. */
1941  Assert(pid != 0);
1942 
1943  /*
1944  * Get lock protecting the group fields. Note LockHashPartitionLockByProc
1945  * calculates the proc number based on the PGPROC slot without looking at
1946  * its contents, so we will acquire the correct lock even if the leader
1947  * PGPROC is in process of being recycled.
1948  */
1949  leader_lwlock = LockHashPartitionLockByProc(leader);
1950  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1951 
1952  /* Is this the leader we're looking for? */
1953  if (leader->pid == pid && leader->lockGroupLeader == leader)
1954  {
1955  /* OK, join the group */
1956  ok = true;
1957  MyProc->lockGroupLeader = leader;
1959  }
1960  LWLockRelease(leader_lwlock);
1961 
1962  return ok;
1963 }
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 1846 of file proc.c.

1847 {
1848  int save_errno = errno;
1849 
1850  got_deadlock_timeout = true;
1851 
1852  /*
1853  * Have to set the latch again, even if handle_sig_alarm already did. Back
1854  * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1855  * ever would be a problem, but setting a set latch again is cheap.
1856  *
1857  * Note that, when this function runs inside procsignal_sigusr1_handler(),
1858  * the handler function sets the latch again after the latch is set here.
1859  */
1860  SetLatch(MyLatch);
1861  errno = save_errno;
1862 }
struct Latch * MyLatch
Definition: globals.c:62
void SetLatch(Latch *latch)
Definition: latch.c:632
static volatile sig_atomic_t got_deadlock_timeout
Definition: proc.c:89

References got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres(), and ProcessRecoveryConflictInterrupt().

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 672 of file proc.c.

673 {
674  /* use volatile pointer to prevent code rearrangement */
675  volatile PROC_HDR *procglobal = ProcGlobal;
676 
677  return procglobal->startupBufferPinWaitBufId;
678 }
PROC_HDR * ProcGlobal
Definition: proc.c:79
Definition: proc.h:377
int startupBufferPinWaitBufId
Definition: proc.h:417

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and ProcessRecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int *  nfree 
)

Definition at line 688 of file proc.c.

689 {
690  dlist_iter iter;
691 
692  Assert(n > 0);
693  Assert(nfree);
694 
696 
697  *nfree = 0;
699  {
700  (*nfree)++;
701  if (*nfree == n)
702  break;
703  }
704 
706 
707  return (*nfree == n);
708 }
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#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:399

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 524 of file proc.c.

525 {
526  PGPROC *auxproc;
527  int proctype;
528 
529  /*
530  * ProcGlobal should be set up already (if we are a backend, we inherit
531  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
532  */
533  if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
534  elog(PANIC, "proc header uninitialized");
535 
536  if (MyProc != NULL)
537  elog(ERROR, "you already exist");
538 
539  /*
540  * We use the ProcStructLock to protect assignment and releasing of
541  * AuxiliaryProcs entries.
542  *
543  * While we are holding the ProcStructLock, also copy the current shared
544  * estimate of spins_per_delay to local storage.
545  */
547 
549 
550  /*
551  * Find a free auxproc ... *big* trouble if there isn't one ...
552  */
553  for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
554  {
555  auxproc = &AuxiliaryProcs[proctype];
556  if (auxproc->pid == 0)
557  break;
558  }
559  if (proctype >= NUM_AUXILIARY_PROCS)
560  {
562  elog(FATAL, "all AuxiliaryProcs are in use");
563  }
564 
565  /* Mark auxiliary proc as in use by me */
566  /* use volatile pointer to prevent code rearrangement */
567  ((volatile PGPROC *) auxproc)->pid = MyProcPid;
568 
570 
571  MyProc = auxproc;
573 
574  /*
575  * Initialize all fields of MyProc, except for those previously
576  * initialized by InitProcGlobal.
577  */
580  MyProc->fpVXIDLock = false;
590  MyProc->delayChkptFlags = 0;
591  MyProc->statusFlags = 0;
593  MyProc->lwWaitMode = 0;
594  MyProc->waitLock = NULL;
595  MyProc->waitProcLock = NULL;
597 #ifdef USE_ASSERT_CHECKING
598  {
599  int i;
600 
601  /* Last process should have released all locks. */
602  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
604  }
605 #endif
606 
607  /*
608  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
609  * on it. That allows us to repoint the process latch, which so far
610  * points to process local one, to the shared one.
611  */
614 
615  /* now that we have a proc, report wait events to shared memory */
617 
618  /* Check that group locking fields are in a proper initial state. */
619  Assert(MyProc->lockGroupLeader == NULL);
621 
622  /*
623  * We might be reusing a semaphore that belonged to a failed process. So
624  * be careful and reinitialize its value here. (This is not strictly
625  * necessary anymore, but seems like a good idea for cleanliness.)
626  */
628 
629  /*
630  * Arrange to clean up at process exit.
631  */
633 
634  /*
635  * Now that we have a PGPROC, we could try to acquire lightweight locks.
636  * Initialize local state needed for them. (Heavyweight locks cannot be
637  * acquired in aux processes.)
638  */
640 
641 #ifdef EXEC_BACKEND
642 
643  /*
644  * Initialize backend-local pointers to all the shared data structures.
645  * (We couldn't do this until now because it needs LWLocks.)
646  */
647  if (IsUnderPostmaster)
648  AttachSharedMemoryStructs();
649 #endif
650 }
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:46
ProcNumber MyProcNumber
Definition: globals.c:89
bool IsUnderPostmaster
Definition: globals.c:119
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:73
void OwnLatch(Latch *latch)
Definition: latch.c:463
#define InvalidLocalTransactionId
Definition: lock.h:65
void InitLWLockAccess(void)
Definition: lwlock.c:557
@ LW_WS_NOT_WAITING
Definition: lwlock.h:30
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:97
#define AmBackgroundWorkerProcess()
Definition: miscadmin.h:373
void SwitchToSharedLatch(void)
Definition: miscinit.c:221
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:294
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
#define GetNumberFromPGProc(proc)
Definition: proc.h:428
@ PROC_WAIT_STATUS_OK
Definition: proc.h:119
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
void set_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:208
static void AuxiliaryProcKill(int code, Datum arg)
Definition: proc.c:973
TransactionId xmin
Definition: proc.h:172
LocalTransactionId lxid
Definition: proc.h:195
PROCLOCK * waitProcLock
Definition: proc.h:228
uint8 lwWaitMode
Definition: proc.h:219
uint32 wait_event_info
Definition: proc.h:274
uint8 statusFlags
Definition: proc.h:237
Oid databaseId
Definition: proc.h:202
pg_atomic_uint64 waitStart
Definition: proc.h:232
bool fpVXIDLock
Definition: proc.h:291
ProcNumber procNumber
Definition: proc.h:190
bool isBackgroundWorker
Definition: proc.h:208
LOCK * waitLock
Definition: proc.h:227
TransactionId xid
Definition: proc.h:167
int delayChkptFlags
Definition: proc.h:235
struct PGPROC::@119 vxid
LocalTransactionId fpLocalTransactionId
Definition: proc.h:292
PGSemaphore sem
Definition: proc.h:161
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:256
Oid roleId
Definition: proc.h:203
ProcWaitStatus waitStatus
Definition: proc.h:162
Oid tempNamespaceId
Definition: proc.h:205
dlist_node links
Definition: proc.h:158
uint8 lwWaiting
Definition: proc.h:218
Latch procLatch
Definition: proc.h:164
int spins_per_delay
Definition: proc.h:415
#define InvalidTransactionId
Definition: transam.h:31
void pgstat_set_wait_event_storage(uint32 *wait_event_info)
Definition: wait_event.c:350

References AmBackgroundWorkerProcess, 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::isBackgroundWorker, 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, 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 297 of file proc.c.

298 {
299  dlist_head *procgloballist;
300 
301  /*
302  * ProcGlobal should be set up already (if we are a backend, we inherit
303  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
304  */
305  if (ProcGlobal == NULL)
306  elog(PANIC, "proc header uninitialized");
307 
308  if (MyProc != NULL)
309  elog(ERROR, "you already exist");
310 
311  /* Decide which list should supply our PGPROC. */
313  procgloballist = &ProcGlobal->autovacFreeProcs;
314  else if (AmBackgroundWorkerProcess())
315  procgloballist = &ProcGlobal->bgworkerFreeProcs;
316  else if (AmWalSenderProcess())
317  procgloballist = &ProcGlobal->walsenderFreeProcs;
318  else
319  procgloballist = &ProcGlobal->freeProcs;
320 
321  /*
322  * Try to get a proc struct from the appropriate free list. If this
323  * fails, we must be out of PGPROC structures (not to mention semaphores).
324  *
325  * While we are holding the ProcStructLock, also copy the current shared
326  * estimate of spins_per_delay to local storage.
327  */
329 
331 
332  if (!dlist_is_empty(procgloballist))
333  {
336  }
337  else
338  {
339  /*
340  * If we reach here, all the PGPROCs are in use. This is one of the
341  * possible places to detect "too many backends", so give the standard
342  * error message. XXX do we need to give a different failure message
343  * in the autovacuum case?
344  */
346  if (AmWalSenderProcess())
347  ereport(FATAL,
348  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
349  errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
350  max_wal_senders)));
351  ereport(FATAL,
352  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
353  errmsg("sorry, too many clients already")));
354  }
356 
357  /*
358  * Cross-check that the PGPROC is of the type we expect; if this were not
359  * the case, it would get returned to the wrong list.
360  */
361  Assert(MyProc->procgloballist == procgloballist);
362 
363  /*
364  * Now that we have a PGPROC, mark ourselves as an active postmaster
365  * child; this is so that the postmaster can detect it if we exit without
366  * cleaning up. (XXX autovac launcher currently doesn't participate in
367  * this; it probably should.)
368  *
369  * Slot sync worker also does not participate in it, see comments atop
370  * 'struct bkend' in postmaster.c.
371  */
375 
376  /*
377  * Initialize all fields of MyProc, except for those previously
378  * initialized by InitProcGlobal.
379  */
382  MyProc->fpVXIDLock = false;
386  MyProc->pid = MyProcPid;
389  /* databaseId and roleId will be filled in later */
394  MyProc->delayChkptFlags = 0;
395  MyProc->statusFlags = 0;
396  /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
400  MyProc->lwWaitMode = 0;
401  MyProc->waitLock = NULL;
402  MyProc->waitProcLock = NULL;
404 #ifdef USE_ASSERT_CHECKING
405  {
406  int i;
407 
408  /* Last process should have released all locks. */
409  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
411  }
412 #endif
414 
415  /* Initialize fields for sync rep */
416  MyProc->waitLSN = 0;
419 
420  /* Initialize fields for group XID clearing. */
421  MyProc->procArrayGroupMember = false;
424 
425  /* Check that group locking fields are in a proper initial state. */
426  Assert(MyProc->lockGroupLeader == NULL);
428 
429  /* Initialize wait event information. */
430  MyProc->wait_event_info = 0;
431 
432  /* Initialize fields for group transaction status update. */
433  MyProc->clogGroupMember = false;
439 
440  /*
441  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
442  * on it. That allows us to repoint the process latch, which so far
443  * points to process local one, to the shared one.
444  */
447 
448  /* now that we have a proc, report wait events to shared memory */
450 
451  /*
452  * We might be reusing a semaphore that belonged to a failed process. So
453  * be careful and reinitialize its value here. (This is not strictly
454  * necessary anymore, but seems like a good idea for cleanliness.)
455  */
457 
458  /*
459  * Arrange to clean up at backend exit.
460  */
462 
463  /*
464  * Now that we have a PGPROC, we could try to acquire locks, so initialize
465  * local state needed for LWLocks, and the deadlock checker.
466  */
469 
470 #ifdef EXEC_BACKEND
471 
472  /*
473  * Initialize backend-local pointers to all the shared data structures.
474  * (We couldn't do this until now because it needs LWLocks.)
475  */
476  if (IsUnderPostmaster)
477  AttachSharedMemoryStructs();
478 #endif
479 }
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:143
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition: ilist.h:450
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
#define AmAutoVacuumWorkerProcess()
Definition: miscadmin.h:372
#define AmWalSenderProcess()
Definition: miscadmin.h:374
#define AmLogicalSlotSyncWorkerProcess()
Definition: miscadmin.h:375
#define AmAutoVacuumLauncherProcess()
Definition: miscadmin.h:371
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:323
#define PROC_IS_AUTOVACUUM
Definition: proc.h:57
static void ProcKill(int code, Datum arg)
Definition: proc.c:835
bool procArrayGroupMember
Definition: proc.h:264
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:284
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:266
dlist_head * procgloballist
Definition: proc.h:159
bool recoveryConflictPending
Definition: proc.h:215
TransactionId clogGroupMemberXid
Definition: proc.h:279
int64 clogGroupMemberPage
Definition: proc.h:282
bool clogGroupMember
Definition: proc.h:277
XLogRecPtr waitLSN
Definition: proc.h:247
dlist_node syncRepLinks
Definition: proc.h:249
int syncRepState
Definition: proc.h:248
pg_atomic_uint32 clogGroupNext
Definition: proc.h:278
XidStatus clogGroupMemberXidStatus
Definition: proc.h:280
TransactionId procArrayGroupMemberXid
Definition: proc.h:272
dlist_head autovacFreeProcs
Definition: proc.h:401
dlist_head walsenderFreeProcs
Definition: proc.h:405
dlist_head bgworkerFreeProcs
Definition: proc.h:403
#define SYNC_REP_NOT_WAITING
Definition: syncrep.h:30
int max_wal_senders
Definition: walsender.c:121
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static struct link * links
Definition: zic.c:299

References AmAutoVacuumLauncherProcess, AmAutoVacuumWorkerProcess, AmBackgroundWorkerProcess, AmLogicalSlotSyncWorkerProcess, 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::isBackgroundWorker, IsUnderPostmaster, PGPROC::links, links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LW_WS_NOT_WAITING, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, MarkPostmasterChildActive(), 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, 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 AutoVacWorkerMain(), BackendMain(), BackgroundWorkerMain(), BootstrapModeMain(), PostgresSingleUserMain(), and ReplSlotSyncWorkerMain().

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 489 of file proc.c.

490 {
491  Assert(MyProc != NULL);
492 
493  /*
494  * Add our PGPROC to the PGPROC array in shared memory.
495  */
497 
498  /*
499  * Arrange to clean that up at backend exit.
500  */
502 }
void ProcArrayAdd(PGPROC *proc)
Definition: procarray.c:468
static void RemoveProcFromArray(int code, Datum arg)
Definition: proc.c:824

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 158 of file proc.c.

159 {
160  PGPROC *procs;
161  int i,
162  j;
163  bool found;
165 
166  /* Create the ProcGlobal shared structure */
167  ProcGlobal = (PROC_HDR *)
168  ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
169  Assert(!found);
170 
171  /*
172  * Initialize the data structures.
173  */
180  ProcGlobal->walwriterLatch = NULL;
184 
185  /*
186  * Create and initialize all the PGPROC structures we'll need. There are
187  * five separate consumers: (1) normal backends, (2) autovacuum workers
188  * and the autovacuum launcher, (3) background workers, (4) auxiliary
189  * processes, and (5) prepared transactions. Each PGPROC structure is
190  * dedicated to exactly one of these purposes, and they do not move
191  * between groups.
192  */
193  procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
194  MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
195  ProcGlobal->allProcs = procs;
196  /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
198 
199  /*
200  * Allocate arrays mirroring PGPROC fields in a dense manner. See
201  * PROC_HDR.
202  *
203  * XXX: It might make sense to increase padding for these arrays, given
204  * how hotly they are accessed.
205  */
206  ProcGlobal->xids =
207  (TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids));
208  MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids));
210  MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates));
211  ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags));
212  MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags));
213 
214  for (i = 0; i < TotalProcs; i++)
215  {
216  PGPROC *proc = &procs[i];
217 
218  /* Common initialization for all PGPROCs, regardless of type. */
219 
220  /*
221  * Set up per-PGPROC semaphore, latch, and fpInfoLock. Prepared xact
222  * dummy PGPROCs don't need these though - they're never associated
223  * with a real process
224  */
226  {
227  proc->sem = PGSemaphoreCreate();
228  InitSharedLatch(&(proc->procLatch));
230  }
231 
232  /*
233  * Newly created PGPROCs for normal backends, autovacuum and bgworkers
234  * must be queued up on the appropriate free list. Because there can
235  * only ever be a small, fixed number of auxiliary processes, no free
236  * list is used in that case; InitAuxiliaryProcess() instead uses a
237  * linear search. PGPROCs for prepared transactions are added to a
238  * free list by TwoPhaseShmemInit().
239  */
240  if (i < MaxConnections)
241  {
242  /* PGPROC for normal backend, add to freeProcs list */
245  }
246  else if (i < MaxConnections + autovacuum_max_workers + 1)
247  {
248  /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */
251  }
253  {
254  /* PGPROC for bgworker, add to bgworkerFreeProcs list */
257  }
258  else if (i < MaxBackends)
259  {
260  /* PGPROC for walsender, add to walsenderFreeProcs list */
263  }
264 
265  /* Initialize myProcLocks[] shared memory queues. */
266  for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
267  dlist_init(&(proc->myProcLocks[j]));
268 
269  /* Initialize lockGroupMembers list. */
271 
272  /*
273  * Initialize the atomic variables, otherwise, it won't be safe to
274  * access them for backends that aren't currently in use.
275  */
278  pg_atomic_init_u64(&(proc->waitStart), 0);
279  }
280 
281  /*
282  * Save pointers to the blocks of PGPROC structures reserved for auxiliary
283  * processes and prepared transactions.
284  */
285  AuxiliaryProcs = &procs[MaxBackends];
287 
288  /* Create ProcStructLock spinlock, too */
289  ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
291 }
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_max_workers
Definition: autovacuum.c:118
unsigned int uint32
Definition: c.h:506
unsigned char uint8
Definition: c.h:504
#define MemSet(start, val, len)
Definition: c.h:1020
uint32 TransactionId
Definition: c.h:652
int MaxConnections
Definition: globals.c:142
int MaxBackends
Definition: globals.c:145
int max_worker_processes
Definition: globals.c:143
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
int j
Definition: isn.c:74
void InitSharedLatch(Latch *latch)
Definition: latch.c:430
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:707
@ LWTRANCHE_LOCK_FASTPATH
Definition: lwlock.h:190
PGSemaphore PGSemaphoreCreate(void)
Definition: posix_sema.c:261
#define DEFAULT_SPINS_PER_DELAY
Definition: s_lock.h:714
void * ShmemAlloc(Size size)
Definition: shmem.c:152
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
LWLock fpInfoLock
Definition: proc.h:288
uint8 * statusFlags
Definition: proc.h:394
XidCacheStatus * subxidStates
Definition: proc.h:388
Latch * walwriterLatch
Definition: proc.h:411
PGPROC * allProcs
Definition: proc.h:379
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:409
TransactionId * xids
Definition: proc.h:382
Latch * checkpointerLatch
Definition: proc.h:413
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:407
uint32 allProcCount
Definition: proc.h:397
int max_prepared_xacts
Definition: twophase.c:115

References PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert, PROC_HDR::autovacFreeProcs, autovacuum_max_workers, AuxiliaryProcs, PROC_HDR::bgworkerFreeProcs, PROC_HDR::checkpointerLatch, PROC_HDR::clogGroupFirst, PGPROC::clogGroupNext, DEFAULT_SPINS_PER_DELAY, dlist_init(), dlist_push_tail(), PGPROC::fpInfoLock, PROC_HDR::freeProcs, i, InitSharedLatch(), INVALID_PROC_NUMBER, j, PGPROC::links, PGPROC::lockGroupMembers, LWLockInitialize(), LWTRANCHE_LOCK_FASTPATH, max_prepared_xacts, max_worker_processes, MaxBackends, MaxConnections, MemSet, PGPROC::myProcLocks, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, pg_atomic_init_u32(), pg_atomic_init_u64(), PGSemaphoreCreate(), PreparedXactProcs, PROC_HDR::procArrayGroupFirst, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::procgloballist, PGPROC::procLatch, ProcStructLock, PGPROC::sem, ShmemAlloc(), ShmemInitStruct(), SpinLockInit, PROC_HDR::spins_per_delay, PROC_HDR::startupBufferPinWaitBufId, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PGPROC::waitStart, PROC_HDR::walsenderFreeProcs, PROC_HDR::walwriterLatch, and PROC_HDR::xids.

Referenced by CreateOrAttachShmemStructs().

◆ IsWaitingForLock()

bool IsWaitingForLock ( void  )

Definition at line 714 of file proc.c.

715 {
716  if (lockAwaited == NULL)
717  return false;
718 
719  return true;
720 }
static LOCALLOCK * lockAwaited
Definition: proc.c:84

References lockAwaited.

Referenced by ProcessRecoveryConflictInterrupt().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 731 of file proc.c.

732 {
733  LWLock *partitionLock;
734  DisableTimeoutParams timeouts[2];
735 
736  HOLD_INTERRUPTS();
737 
739 
740  /* Nothing to do if we weren't waiting for a lock */
741  if (lockAwaited == NULL)
742  {
744  return;
745  }
746 
747  /*
748  * Turn off the deadlock and lock timeout timers, if they are still
749  * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
750  * indicator flag, since this function is executed before
751  * ProcessInterrupts when responding to SIGINT; else we'd lose the
752  * knowledge that the SIGINT came from a lock timeout and not an external
753  * source.
754  */
755  timeouts[0].id = DEADLOCK_TIMEOUT;
756  timeouts[0].keep_indicator = false;
757  timeouts[1].id = LOCK_TIMEOUT;
758  timeouts[1].keep_indicator = true;
759  disable_timeouts(timeouts, 2);
760 
761  /* Unlink myself from the wait queue, if on it (might not be anymore!) */
762  partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
763  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
764 
766  {
767  /* We could not have been granted the lock yet */
769  }
770  else
771  {
772  /*
773  * Somebody kicked us off the lock queue already. Perhaps they
774  * granted us the lock, or perhaps they detected a deadlock. If they
775  * did grant us the lock, we'd better remember it in our local lock
776  * table.
777  */
780  }
781 
782  lockAwaited = NULL;
783 
784  LWLockRelease(partitionLock);
785 
787 }
static bool dlist_node_is_detached(const dlist_node *node)
Definition: ilist.h:525
void GrantAwaitedLock(void)
Definition: lock.c:1788
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1907
void AbortStrongLockAcquire(void)
Definition: lock.c:1759
#define LockHashPartitionLock(hashcode)
Definition: lock.h:526
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:135
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:133
TimeoutId id
Definition: timeout.h:71
uint32 hashcode
Definition: lock.h:432
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(), GrantAwaitedLock(), LOCALLOCK::hashcode, HOLD_INTERRUPTS, DisableTimeoutParams::id, DisableTimeoutParams::keep_indicator, PGPROC::links, LOCK_TIMEOUT, lockAwaited, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), RESUME_INTERRUPTS, and PGPROC::waitStatus.

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

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 123 of file proc.c.

124 {
125  /*
126  * We need a sema per backend (including autovacuum), plus one for each
127  * auxiliary process.
128  */
130 }

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 101 of file proc.c.

102 {
103  Size size = 0;
104  Size TotalProcs =
106 
107  /* ProcGlobal */
108  size = add_size(size, sizeof(PROC_HDR));
109  size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
110  size = add_size(size, sizeof(slock_t));
111 
112  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
113  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
114  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
115 
116  return size;
117 }
size_t Size
Definition: c.h:605
Size add_size(Size s1, Size s2)
Definition: shmem.c:493
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
static pg_noinline void Size size
Definition: slab.c:607

References add_size(), max_prepared_xacts, MaxBackends, mul_size(), NUM_AUXILIARY_PROCS, ProcGlobal, size, PROC_HDR::statusFlags, PROC_HDR::subxidStates, and PROC_HDR::xids.

Referenced by CalculateShmemSize().

◆ ProcLockWakeup()

void ProcLockWakeup ( LockMethod  lockMethodTable,
LOCK lock 
)

Definition at line 1712 of file proc.c.

1713 {
1714  dclist_head *waitQueue = &lock->waitProcs;
1715  LOCKMASK aheadRequests = 0;
1716  dlist_mutable_iter miter;
1717 
1718  if (dclist_is_empty(waitQueue))
1719  return;
1720 
1721  dclist_foreach_modify(miter, waitQueue)
1722  {
1723  PGPROC *proc = dlist_container(PGPROC, links, miter.cur);
1724  LOCKMODE lockmode = proc->waitLockMode;
1725 
1726  /*
1727  * Waken if (a) doesn't conflict with requests of earlier waiters, and
1728  * (b) doesn't conflict with already-held locks.
1729  */
1730  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1731  !LockCheckConflicts(lockMethodTable, lockmode, lock,
1732  proc->waitProcLock))
1733  {
1734  /* OK to waken */
1735  GrantLock(lock, proc->waitProcLock, lockmode);
1736  /* removes proc from the lock's waiting process queue */
1738  }
1739  else
1740  {
1741  /*
1742  * Lock conflicts: Don't wake, but remember requested mode for
1743  * later checks.
1744  */
1745  aheadRequests |= LOCKBIT_ON(lockmode);
1746  }
1747  }
1748 }
static bool dclist_is_empty(const dclist_head *head)
Definition: ilist.h:682
#define dclist_foreach_modify(iter, lhead)
Definition: ilist.h:973
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1557
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1428
#define LOCKBIT_ON(lockmode)
Definition: lock.h:84
int LOCKMODE
Definition: lockdefs.h:26
int LOCKMASK
Definition: lockdefs.h:25
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition: proc.c:1684
dclist_head waitProcs
Definition: lock.h:317
const LOCKMASK * conflictTab
Definition: lock.h:111
LOCKMODE waitLockMode
Definition: proc.h:229
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 807 of file proc.c.

808 {
809  if (!MyProc)
810  return;
811  /* If waiting, get off wait queue (should only be needed after error) */
813  /* Release standard locks, including session-level if aborting */
815  /* Release transaction-level advisory locks */
817 }
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2168
#define DEFAULT_LOCKMETHOD
Definition: lock.h:125
#define USER_LOCKMETHOD
Definition: lock.h:126
void LockErrorCleanup(void)
Definition: proc.c:731

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( ProcNumber  procNumber)

Definition at line 1884 of file proc.c.

1885 {
1886  if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
1887  elog(ERROR, "procNumber out of range");
1888 
1889  SetLatch(&ProcGlobal->allProcs[procNumber].procLatch);
1890 }

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

Referenced by ReleasePredicateLocks(), and UnpinBufferNoOwner().

◆ ProcSleep()

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

Definition at line 1072 of file proc.c.

1073 {
1074  LOCKMODE lockmode = locallock->tag.mode;
1075  LOCK *lock = locallock->lock;
1076  PROCLOCK *proclock = locallock->proclock;
1077  uint32 hashcode = locallock->hashcode;
1078  LWLock *partitionLock = LockHashPartitionLock(hashcode);
1079  dclist_head *waitQueue = &lock->waitProcs;
1080  PGPROC *insert_before = NULL;
1081  LOCKMASK myHeldLocks = MyProc->heldLocks;
1082  TimestampTz standbyWaitStart = 0;
1083  bool early_deadlock = false;
1084  bool allow_autovacuum_cancel = true;
1085  bool logged_recovery_conflict = false;
1086  ProcWaitStatus myWaitStatus;
1087  PGPROC *leader = MyProc->lockGroupLeader;
1088 
1089  /*
1090  * If group locking is in use, locks held by members of my locking group
1091  * need to be included in myHeldLocks. This is not required for relation
1092  * extension lock which conflict among group members. However, including
1093  * them in myHeldLocks will give group members the priority to get those
1094  * locks as compared to other backends which are also trying to acquire
1095  * those locks. OTOH, we can avoid giving priority to group members for
1096  * that kind of locks, but there doesn't appear to be a clear advantage of
1097  * the same.
1098  */
1099  if (leader != NULL)
1100  {
1101  dlist_iter iter;
1102 
1103  dlist_foreach(iter, &lock->procLocks)
1104  {
1105  PROCLOCK *otherproclock;
1106 
1107  otherproclock = dlist_container(PROCLOCK, lockLink, iter.cur);
1108 
1109  if (otherproclock->groupLeader == leader)
1110  myHeldLocks |= otherproclock->holdMask;
1111  }
1112  }
1113 
1114  /*
1115  * Determine where to add myself in the wait queue.
1116  *
1117  * Normally I should go at the end of the queue. However, if I already
1118  * hold locks that conflict with the request of any previous waiter, put
1119  * myself in the queue just in front of the first such waiter. This is not
1120  * a necessary step, since deadlock detection would move me to before that
1121  * waiter anyway; but it's relatively cheap to detect such a conflict
1122  * immediately, and avoid delaying till deadlock timeout.
1123  *
1124  * Special case: if I find I should go in front of some waiter, check to
1125  * see if I conflict with already-held locks or the requests before that
1126  * waiter. If not, then just grant myself the requested lock immediately.
1127  * This is the same as the test for immediate grant in LockAcquire, except
1128  * we are only considering the part of the wait queue before my insertion
1129  * point.
1130  */
1131  if (myHeldLocks != 0 && !dclist_is_empty(waitQueue))
1132  {
1133  LOCKMASK aheadRequests = 0;
1134  dlist_iter iter;
1135 
1136  dclist_foreach(iter, waitQueue)
1137  {
1138  PGPROC *proc = dlist_container(PGPROC, links, iter.cur);
1139 
1140  /*
1141  * If we're part of the same locking group as this waiter, its
1142  * locks neither conflict with ours nor contribute to
1143  * aheadRequests.
1144  */
1145  if (leader != NULL && leader == proc->lockGroupLeader)
1146  continue;
1147 
1148  /* Must he wait for me? */
1149  if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
1150  {
1151  /* Must I wait for him ? */
1152  if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
1153  {
1154  /*
1155  * Yes, so we have a deadlock. Easiest way to clean up
1156  * correctly is to call RemoveFromWaitQueue(), but we
1157  * can't do that until we are *on* the wait queue. So, set
1158  * a flag to check below, and break out of loop. Also,
1159  * record deadlock info for later message.
1160  */
1161  RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
1162  early_deadlock = true;
1163  break;
1164  }
1165  /* I must go before this waiter. Check special case. */
1166  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1167  !LockCheckConflicts(lockMethodTable, lockmode, lock,
1168  proclock))
1169  {
1170  /* Skip the wait and just grant myself the lock. */
1171  GrantLock(lock, proclock, lockmode);
1172  GrantAwaitedLock();
1173  return PROC_WAIT_STATUS_OK;
1174  }
1175 
1176  /* Put myself into wait queue before conflicting process */
1177  insert_before = proc;
1178  break;
1179  }
1180  /* Nope, so advance to next waiter */
1181  aheadRequests |= LOCKBIT_ON(proc->waitLockMode);
1182  }
1183  }
1184 
1185  /*
1186  * At this point we know that we'd really need to sleep. If we've been
1187  * commanded not to do that, bail out.
1188  */
1189  if (dontWait)
1190  return PROC_WAIT_STATUS_ERROR;
1191 
1192  /*
1193  * Insert self into queue, at the position determined above.
1194  */
1195  if (insert_before)
1196  dclist_insert_before(waitQueue, &insert_before->links, &MyProc->links);
1197  else
1198  dclist_push_tail(waitQueue, &MyProc->links);
1199 
1200  lock->waitMask |= LOCKBIT_ON(lockmode);
1201 
1202  /* Set up wait information in PGPROC object, too */
1203  MyProc->waitLock = lock;
1204  MyProc->waitProcLock = proclock;
1205  MyProc->waitLockMode = lockmode;
1206 
1208 
1209  /*
1210  * If we detected deadlock, give up without waiting. This must agree with
1211  * CheckDeadLock's recovery code.
1212  */
1213  if (early_deadlock)
1214  {
1215  RemoveFromWaitQueue(MyProc, hashcode);
1216  return PROC_WAIT_STATUS_ERROR;
1217  }
1218 
1219  /* mark that we are waiting for a lock */
1220  lockAwaited = locallock;
1221 
1222  /*
1223  * Release the lock table's partition lock.
1224  *
1225  * NOTE: this may also cause us to exit critical-section state, possibly
1226  * allowing a cancel/die interrupt to be accepted. This is OK because we
1227  * have recorded the fact that we are waiting for a lock, and so
1228  * LockErrorCleanup will clean up if cancel/die happens.
1229  */
1230  LWLockRelease(partitionLock);
1231 
1232  /*
1233  * Also, now that we will successfully clean up after an ereport, it's
1234  * safe to check to see if there's a buffer pin deadlock against the
1235  * Startup process. Of course, that's only necessary if we're doing Hot
1236  * Standby and are not the Startup process ourselves.
1237  */
1238  if (RecoveryInProgress() && !InRecovery)
1240 
1241  /* Reset deadlock_state before enabling the timeout handler */
1243  got_deadlock_timeout = false;
1244 
1245  /*
1246  * Set timer so we can wake up after awhile and check for a deadlock. If a
1247  * deadlock is detected, the handler sets MyProc->waitStatus =
1248  * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
1249  * rather than success.
1250  *
1251  * By delaying the check until we've waited for a bit, we can avoid
1252  * running the rather expensive deadlock-check code in most cases.
1253  *
1254  * If LockTimeout is set, also enable the timeout for that. We can save a
1255  * few cycles by enabling both timeout sources in one call.
1256  *
1257  * If InHotStandby we set lock waits slightly later for clarity with other
1258  * code.
1259  */
1260  if (!InHotStandby)
1261  {
1262  if (LockTimeout > 0)
1263  {
1264  EnableTimeoutParams timeouts[2];
1265 
1266  timeouts[0].id = DEADLOCK_TIMEOUT;
1267  timeouts[0].type = TMPARAM_AFTER;
1268  timeouts[0].delay_ms = DeadlockTimeout;
1269  timeouts[1].id = LOCK_TIMEOUT;
1270  timeouts[1].type = TMPARAM_AFTER;
1271  timeouts[1].delay_ms = LockTimeout;
1272  enable_timeouts(timeouts, 2);
1273  }
1274  else
1276 
1277  /*
1278  * Use the current time obtained for the deadlock timeout timer as
1279  * waitStart (i.e., the time when this process started waiting for the
1280  * lock). Since getting the current time newly can cause overhead, we
1281  * reuse the already-obtained time to avoid that overhead.
1282  *
1283  * Note that waitStart is updated without holding the lock table's
1284  * partition lock, to avoid the overhead by additional lock
1285  * acquisition. This can cause "waitstart" in pg_locks to become NULL
1286  * for a very short period of time after the wait started even though
1287  * "granted" is false. This is OK in practice because we can assume
1288  * that users are likely to look at "waitstart" when waiting for the
1289  * lock for a long time.
1290  */
1293  }
1294  else if (log_recovery_conflict_waits)
1295  {
1296  /*
1297  * Set the wait start timestamp if logging is enabled and in hot
1298  * standby.
1299  */
1300  standbyWaitStart = GetCurrentTimestamp();
1301  }
1302 
1303  /*
1304  * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1305  * will not wait. But a set latch does not necessarily mean that the lock
1306  * is free now, as there are many other sources for latch sets than
1307  * somebody releasing the lock.
1308  *
1309  * We process interrupts whenever the latch has been set, so cancel/die
1310  * interrupts are processed quickly. This means we must not mind losing
1311  * control to a cancel/die interrupt here. We don't, because we have no
1312  * shared-state-change work to do after being granted the lock (the
1313  * grantor did it all). We do have to worry about canceling the deadlock
1314  * timeout and updating the locallock table, but if we lose control to an
1315  * error, LockErrorCleanup will fix that up.
1316  */
1317  do
1318  {
1319  if (InHotStandby)
1320  {
1321  bool maybe_log_conflict =
1322  (standbyWaitStart != 0 && !logged_recovery_conflict);
1323 
1324  /* Set a timer and wait for that or for the lock to be granted */
1326  maybe_log_conflict);
1327 
1328  /*
1329  * Emit the log message if the startup process is waiting longer
1330  * than deadlock_timeout for recovery conflict on lock.
1331  */
1332  if (maybe_log_conflict)
1333  {
1335 
1336  if (TimestampDifferenceExceeds(standbyWaitStart, now,
1337  DeadlockTimeout))
1338  {
1339  VirtualTransactionId *vxids;
1340  int cnt;
1341 
1342  vxids = GetLockConflicts(&locallock->tag.lock,
1343  AccessExclusiveLock, &cnt);
1344 
1345  /*
1346  * Log the recovery conflict and the list of PIDs of
1347  * backends holding the conflicting lock. Note that we do
1348  * logging even if there are no such backends right now
1349  * because the startup process here has already waited
1350  * longer than deadlock_timeout.
1351  */
1353  standbyWaitStart, now,
1354  cnt > 0 ? vxids : NULL, true);
1355  logged_recovery_conflict = true;
1356  }
1357  }
1358  }
1359  else
1360  {
1362  PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1364  /* check for deadlocks first, as that's probably log-worthy */
1366  {
1367  CheckDeadLock();
1368  got_deadlock_timeout = false;
1369  }
1371  }
1372 
1373  /*
1374  * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
1375  * else asynchronously. Read it just once per loop to prevent
1376  * surprising behavior (such as missing log messages).
1377  */
1378  myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
1379 
1380  /*
1381  * If we are not deadlocked, but are waiting on an autovacuum-induced
1382  * task, send a signal to interrupt it.
1383  */
1384  if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
1385  {
1386  PGPROC *autovac = GetBlockingAutoVacuumPgproc();
1387  uint8 statusFlags;
1388  uint8 lockmethod_copy;
1389  LOCKTAG locktag_copy;
1390 
1391  /*
1392  * Grab info we need, then release lock immediately. Note this
1393  * coding means that there is a tiny chance that the process
1394  * terminates its current transaction and starts a different one
1395  * before we have a change to send the signal; the worst possible
1396  * consequence is that a for-wraparound vacuum is canceled. But
1397  * that could happen in any case unless we were to do kill() with
1398  * the lock held, which is much more undesirable.
1399  */
1400  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1401  statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
1402  lockmethod_copy = lock->tag.locktag_lockmethodid;
1403  locktag_copy = lock->tag;
1404  LWLockRelease(ProcArrayLock);
1405 
1406  /*
1407  * Only do it if the worker is not working to protect against Xid
1408  * wraparound.
1409  */
1410  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
1411  !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
1412  {
1413  int pid = autovac->pid;
1414 
1415  /* report the case, if configured to do so */
1417  {
1418  StringInfoData locktagbuf;
1419  StringInfoData logbuf; /* errdetail for server log */
1420 
1421  initStringInfo(&locktagbuf);
1422  initStringInfo(&logbuf);
1423  DescribeLockTag(&locktagbuf, &locktag_copy);
1424  appendStringInfo(&logbuf,
1425  "Process %d waits for %s on %s.",
1426  MyProcPid,
1427  GetLockmodeName(lockmethod_copy, lockmode),
1428  locktagbuf.data);
1429 
1430  ereport(DEBUG1,
1431  (errmsg_internal("sending cancel to blocking autovacuum PID %d",
1432  pid),
1433  errdetail_log("%s", logbuf.data)));
1434 
1435  pfree(locktagbuf.data);
1436  pfree(logbuf.data);
1437  }
1438 
1439  /* send the autovacuum worker Back to Old Kent Road */
1440  if (kill(pid, SIGINT) < 0)
1441  {
1442  /*
1443  * There's a race condition here: once we release the
1444  * ProcArrayLock, it's possible for the autovac worker to
1445  * close up shop and exit before we can do the kill().
1446  * Therefore, we do not whinge about no-such-process.
1447  * Other errors such as EPERM could conceivably happen if
1448  * the kernel recycles the PID fast enough, but such cases
1449  * seem improbable enough that it's probably best to issue
1450  * a warning if we see some other errno.
1451  */
1452  if (errno != ESRCH)
1453  ereport(WARNING,
1454  (errmsg("could not send signal to process %d: %m",
1455  pid)));
1456  }
1457  }
1458 
1459  /* prevent signal from being sent again more than once */
1460  allow_autovacuum_cancel = false;
1461  }
1462 
1463  /*
1464  * If awoken after the deadlock check interrupt has run, and
1465  * log_lock_waits is on, then report about the wait.
1466  */
1468  {
1470  lock_waiters_sbuf,
1471  lock_holders_sbuf;
1472  const char *modename;
1473  long secs;
1474  int usecs;
1475  long msecs;
1476  dlist_iter proc_iter;
1477  PROCLOCK *curproclock;
1478  bool first_holder = true,
1479  first_waiter = true;
1480  int lockHoldersNum = 0;
1481 
1482  initStringInfo(&buf);
1483  initStringInfo(&lock_waiters_sbuf);
1484  initStringInfo(&lock_holders_sbuf);
1485 
1486  DescribeLockTag(&buf, &locallock->tag.lock);
1487  modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1488  lockmode);
1491  &secs, &usecs);
1492  msecs = secs * 1000 + usecs / 1000;
1493  usecs = usecs % 1000;
1494 
1495  /*
1496  * we loop over the lock's procLocks to gather a list of all
1497  * holders and waiters. Thus we will be able to provide more
1498  * detailed information for lock debugging purposes.
1499  *
1500  * lock->procLocks contains all processes which hold or wait for
1501  * this lock.
1502  */
1503 
1504  LWLockAcquire(partitionLock, LW_SHARED);
1505 
1506  dlist_foreach(proc_iter, &lock->procLocks)
1507  {
1508  curproclock =
1509  dlist_container(PROCLOCK, lockLink, proc_iter.cur);
1510 
1511  /*
1512  * we are a waiter if myProc->waitProcLock == curproclock; we
1513  * are a holder if it is NULL or something different
1514  */
1515  if (curproclock->tag.myProc->waitProcLock == curproclock)
1516  {
1517  if (first_waiter)
1518  {
1519  appendStringInfo(&lock_waiters_sbuf, "%d",
1520  curproclock->tag.myProc->pid);
1521  first_waiter = false;
1522  }
1523  else
1524  appendStringInfo(&lock_waiters_sbuf, ", %d",
1525  curproclock->tag.myProc->pid);
1526  }
1527  else
1528  {
1529  if (first_holder)
1530  {
1531  appendStringInfo(&lock_holders_sbuf, "%d",
1532  curproclock->tag.myProc->pid);
1533  first_holder = false;
1534  }
1535  else
1536  appendStringInfo(&lock_holders_sbuf, ", %d",
1537  curproclock->tag.myProc->pid);
1538 
1539  lockHoldersNum++;
1540  }
1541  }
1542 
1543  LWLockRelease(partitionLock);
1544 
1546  ereport(LOG,
1547  (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1548  MyProcPid, modename, buf.data, msecs, usecs),
1549  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1550  "Processes holding the lock: %s. Wait queue: %s.",
1551  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1552  else if (deadlock_state == DS_HARD_DEADLOCK)
1553  {
1554  /*
1555  * This message is a bit redundant with the error that will be
1556  * reported subsequently, but in some cases the error report
1557  * might not make it to the log (eg, if it's caught by an
1558  * exception handler), and we want to ensure all long-wait
1559  * events get logged.
1560  */
1561  ereport(LOG,
1562  (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1563  MyProcPid, modename, buf.data, msecs, usecs),
1564  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1565  "Processes holding the lock: %s. Wait queue: %s.",
1566  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1567  }
1568 
1569  if (myWaitStatus == PROC_WAIT_STATUS_WAITING)
1570  ereport(LOG,
1571  (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1572  MyProcPid, modename, buf.data, msecs, usecs),
1573  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1574  "Processes holding the lock: %s. Wait queue: %s.",
1575  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1576  else if (myWaitStatus == PROC_WAIT_STATUS_OK)
1577  ereport(LOG,
1578  (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1579  MyProcPid, modename, buf.data, msecs, usecs)));
1580  else
1581  {
1582  Assert(myWaitStatus == PROC_WAIT_STATUS_ERROR);
1583 
1584  /*
1585  * Currently, the deadlock checker always kicks its own
1586  * process, which means that we'll only see
1587  * PROC_WAIT_STATUS_ERROR when deadlock_state ==
1588  * DS_HARD_DEADLOCK, and there's no need to print redundant
1589  * messages. But for completeness and future-proofing, print
1590  * a message if it looks like someone else kicked us off the
1591  * lock.
1592  */
1594  ereport(LOG,
1595  (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1596  MyProcPid, modename, buf.data, msecs, usecs),
1597  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1598  "Processes holding the lock: %s. Wait queue: %s.",
1599  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1600  }
1601 
1602  /*
1603  * At this point we might still need to wait for the lock. Reset
1604  * state so we don't print the above messages again.
1605  */
1607 
1608  pfree(buf.data);
1609  pfree(lock_holders_sbuf.data);
1610  pfree(lock_waiters_sbuf.data);
1611  }
1612  } while (myWaitStatus == PROC_WAIT_STATUS_WAITING);
1613 
1614  /*
1615  * Disable the timers, if they are still running. As in LockErrorCleanup,
1616  * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1617  * already caused QueryCancelPending to become set, we want the cancel to
1618  * be reported as a lock timeout, not a user cancel.
1619  */
1620  if (!InHotStandby)
1621  {
1622  if (LockTimeout > 0)
1623  {
1624  DisableTimeoutParams timeouts[2];
1625 
1626  timeouts[0].id = DEADLOCK_TIMEOUT;
1627  timeouts[0].keep_indicator = false;
1628  timeouts[1].id = LOCK_TIMEOUT;
1629  timeouts[1].keep_indicator = true;
1630  disable_timeouts(timeouts, 2);
1631  }
1632  else
1634  }
1635 
1636  /*
1637  * Emit the log message if recovery conflict on lock was resolved but the
1638  * startup process waited longer than deadlock_timeout for it.
1639  */
1640  if (InHotStandby && logged_recovery_conflict)
1642  standbyWaitStart, GetCurrentTimestamp(),
1643  NULL, false);
1644 
1645  /*
1646  * Re-acquire the lock table's partition lock. We have to do this to hold
1647  * off cancel/die interrupts before we can mess with lockAwaited (else we
1648  * might have a missed or duplicated locallock update).
1649  */
1650  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
1651 
1652  /*
1653  * We no longer want LockErrorCleanup to do anything.
1654  */
1655  lockAwaited = NULL;
1656 
1657  /*
1658  * If we got the lock, be sure to remember it in the locallock table.
1659  */
1661  GrantAwaitedLock();
1662 
1663  /*
1664  * We don't have to do anything else, because the awaker did all the
1665  * necessary update of the lock table and MyProc.
1666  */
1667  return MyProc->waitStatus;
1668 }
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1720
bool TimestampDifferenceExceeds(TimestampTz start_time, TimestampTz stop_time, int msec)
Definition: timestamp.c:1780
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1644
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
int64 TimestampTz
Definition: timestamp.h:39
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition: deadlock.c:287
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition: deadlock.c:1144
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
bool message_level_is_interesting(int elevel)
Definition: elog.c:272
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1272
int errdetail_log(const char *fmt,...)
Definition: elog.c:1251
#define LOG
Definition: elog.h:31
#define WARNING
Definition: elog.h:36
#define DEBUG1
Definition: elog.h:30
static void dclist_push_tail(dclist_head *head, dlist_node *node)
Definition: ilist.h:709
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 ResetLatch(Latch *latch)
Definition: latch.c:724
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:517
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
#define WL_LATCH_SET
Definition: latch.h:127
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1233
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition: lock.c:2893
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:4059
@ DS_HARD_DEADLOCK
Definition: lock.h:513
@ DS_BLOCKED_BY_AUTOVACUUM
Definition: lock.h:514
@ DS_NO_DEADLOCK
Definition: lock.h:511
@ DS_NOT_YET_CHECKED
Definition: lock.h:510
@ DS_SOFT_DEADLOCK
Definition: lock.h:512
#define AccessExclusiveLock
Definition: lockdefs.h:43
@ LW_SHARED
Definition: lwlock.h:115
void pfree(void *pointer)
Definition: mcxt.c:1521
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static char * buf
Definition: pg_test_fsync.c:73
#define PROC_VACUUM_FOR_WRAPAROUND
Definition: proc.h:60
ProcWaitStatus
Definition: proc.h:118
@ PROC_WAIT_STATUS_WAITING
Definition: proc.h:120
@ PROC_WAIT_STATUS_ERROR
Definition: proc.h:121
@ PROCSIG_RECOVERY_CONFLICT_LOCK
Definition: procsignal.h:44
bool log_lock_waits
Definition: proc.c:64
static DeadLockState deadlock_state
Definition: proc.c:86
int DeadlockTimeout
Definition: proc.c:58
static void CheckDeadLock(void)
Definition: proc.c:1760
int LockTimeout
Definition: proc.c:60
void CheckRecoveryConflictDeadlock(void)
Definition: standby.c:904
bool log_recovery_conflict_waits
Definition: standby.c:41
void LogRecoveryConflict(ProcSignalReason reason, TimestampTz wait_start, TimestampTz now, VirtualTransactionId *wait_list, bool still_waiting)
Definition: standby.c:273
void ResolveRecoveryConflictWithLock(LOCKTAG locktag, bool logging_conflict)
Definition: standby.c:622
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
TimeoutType type
Definition: timeout.h:61
TimeoutId id
Definition: timeout.h:60
LOCKTAG lock
Definition: lock.h:410
LOCKMODE mode
Definition: lock.h:411
LOCK * lock
Definition: lock.h:433
PROCLOCK * proclock
Definition: lock.h:434
LOCALLOCKTAG tag
Definition: lock.h:429
Definition: lock.h:165
uint8 locktag_type
Definition: lock.h:170
uint8 locktag_lockmethodid
Definition: lock.h:171
Definition: lock.h:309
LOCKTAG tag
Definition: lock.h:311
LOCKMASK waitMask
Definition: lock.h:315
dlist_head procLocks
Definition: lock.h:316
int pgxactoff
Definition: proc.h:179
LOCKMASK heldLocks
Definition: proc.h:230
PGPROC * myProc
Definition: lock.h:366
Definition: lock.h:370
LOCKMASK holdMask
Definition: lock.h:376
PGPROC * groupLeader
Definition: lock.h:375
PROCLOCKTAG tag
Definition: lock.h:372
dlist_node * cur
Definition: ilist.h:179
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 kill(pid, sig)
Definition: win32_port.h:503
bool RecoveryInProgress(void)
Definition: xlog.c:6333
bool InRecovery
Definition: xlogutils.c:50
#define InHotStandby
Definition: xlogutils.h:60

References AccessExclusiveLock, appendStringInfo(), Assert, buf, CHECK_FOR_INTERRUPTS, CheckDeadLock(), CheckRecoveryConflictDeadlock(), LockMethodData::conflictTab, dlist_iter::cur, StringInfoData::data, dclist_foreach, dclist_insert_before(), dclist_is_empty(), dclist_push_tail(), deadlock_state, DEADLOCK_TIMEOUT, DeadlockTimeout, DEBUG1, EnableTimeoutParams::delay_ms, DescribeLockTag(), disable_timeout(), disable_timeouts(), dlist_container, dlist_foreach, 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(), GetBlockingAutoVacuumPgproc(), GetCurrentTimestamp(), GetLockConflicts(), GetLockmodeName(), got_deadlock_timeout, GrantAwaitedLock(), GrantLock(), PROCLOCK::groupLeader, LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, EnableTimeoutParams::id, DisableTimeoutParams::id, InHotStandby, initStringInfo(), InRecovery, DisableTimeoutParams::keep_indicator, kill, PGPROC::links, links, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_TIMEOUT, lockAwaited, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, LOCKTAG::locktag_lockmethodid, LOCKTAG::locktag_type, LockTimeout, LOG, log_lock_waits, log_recovery_conflict_waits, LogRecoveryConflict(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), message_level_is_interesting(), LOCALLOCKTAG::mode, MyLatch, MyProc, PROCLOCKTAG::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, LOCALLOCK::proclock, LOCK::procLocks, PROCSIG_RECOVERY_CONFLICT_LOCK, RecoveryInProgress(), RememberSimpleDeadLock(), RemoveFromWaitQueue(), ResetLatch(), ResolveRecoveryConflictWithLock(), PROC_HDR::statusFlags, LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, TimestampDifference(), TimestampDifferenceExceeds(), TMPARAM_AFTER, EnableTimeoutParams::type, WaitLatch(), PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, 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 1684 of file proc.c.

1685 {
1686  if (dlist_node_is_detached(&proc->links))
1687  return;
1688 
1690 
1691  /* Remove process from wait queue */
1693 
1694  /* Clean up process' state and pass it the ok/fail signal */
1695  proc->waitLock = NULL;
1696  proc->waitProcLock = NULL;
1697  proc->waitStatus = waitStatus;
1699 
1700  /* And awaken it */
1701  SetLatch(&proc->procLatch);
1702 }
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 660 of file proc.c.

661 {
662  /* use volatile pointer to prevent code rearrangement */
663  volatile PROC_HDR *procglobal = ProcGlobal;
664 
665  procglobal->startupBufferPinWaitBufId = bufid;
666 }

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

Variable Documentation

◆ DeadlockTimeout

◆ 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(), AbortTransaction(), AtEOSubXact_Namespace(), AtEOXact_Namespace(), AtEOXact_Snapshot(), attach_to_queues(), AutoVacWorkerMain(), AuxiliaryProcKill(), BaseInit(), BecomeLockGroupLeader(), BecomeLockGroupMember(), CheckDeadLock(), CheckpointerMain(), 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(), fmgr_sql(), get_cast_hashentry(), GetCurrentVirtualXIDs(), GetLockConflicts(), GetNewTransactionId(), GetSerializableTransactionSnapshotInt(), GetSnapshotData(), GetSnapshotDataReuse(), GetStableLatestTransactionId(), init_sql_fcache(), InitAuxiliaryProcess(), InitBufferManagerAccess(), InitializeParallelDSM(), InitializeSessionUserId(), InitPostgres(), InitProcess(), InitProcessPhase2(), InitRecoveryTransactionEnvironment(), InitTempTableNamespace(), InitWalSenderSlot(), 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_wal_replay_wait(), 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(), 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(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), WaitXLogInsertionsToFinish(), WalReceiverMain(), WalWriterMain(), write_csvlog(), write_jsonlog(), XidCacheRemoveRunningXids(), and XLogSaveBufferForHint().

◆ MyProcNumber

PGDLLIMPORT ProcNumber MyProcNumber
extern

Definition at line 89 of file globals.c.

◆ ParallelLeaderProcNumber

PGDLLIMPORT ProcNumber ParallelLeaderProcNumber
extern

Definition at line 91 of file globals.c.

◆ 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