PostgreSQL Source Code  git master
proc.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/autovacuum.h"
#include "replication/slot.h"
#include "replication/syncrep.h"
#include "storage/condition_variable.h"
#include "storage/standby.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
#include "storage/spin.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
Include dependency graph for proc.c:

Go to the source code of this file.

Functions

static void RemoveProcFromArray (int code, Datum arg)
 
static void ProcKill (int code, Datum arg)
 
static void AuxiliaryProcKill (int code, Datum arg)
 
static void CheckDeadLock (void)
 
Size ProcGlobalShmemSize (void)
 
int ProcGlobalSemas (void)
 
void InitProcGlobal (void)
 
void InitProcess (void)
 
void InitProcessPhase2 (void)
 
void InitAuxiliaryProcess (void)
 
void PublishStartupProcessInformation (void)
 
void SetStartupBufferPinWaitBufId (int bufid)
 
int GetStartupBufferPinWaitBufId (void)
 
bool HaveNFreeProcs (int n)
 
bool IsWaitingForLock (void)
 
void LockErrorCleanup (void)
 
void ProcReleaseLocks (bool isCommit)
 
PGPROCAuxiliaryPidGetProc (int pid)
 
void ProcQueueInit (PROC_QUEUE *queue)
 
int ProcSleep (LOCALLOCK *locallock, LockMethod lockMethodTable)
 
PGPROCProcWakeup (PGPROC *proc, int waitStatus)
 
void ProcLockWakeup (LockMethod lockMethodTable, LOCK *lock)
 
void CheckDeadLockAlert (void)
 
void ProcWaitForSignal (uint32 wait_event_info)
 
void ProcSendSignal (int pid)
 
void BecomeLockGroupLeader (void)
 
bool BecomeLockGroupMember (PGPROC *leader, int pid)
 

Variables

int DeadlockTimeout = 1000
 
int StatementTimeout = 0
 
int LockTimeout = 0
 
int IdleInTransactionSessionTimeout = 0
 
bool log_lock_waits = false
 
PGPROCMyProc = NULL
 
PGXACTMyPgXact = NULL
 
NON_EXEC_STATIC slock_tProcStructLock = NULL
 
PROC_HDRProcGlobal = NULL
 
NON_EXEC_STATIC PGPROCAuxiliaryProcs = NULL
 
PGPROCPreparedXactProcs = NULL
 
static LOCALLOCKlockAwaited = NULL
 
static DeadLockState deadlock_state = DS_NOT_YET_CHECKED
 
static volatile sig_atomic_t got_deadlock_timeout
 

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC* AuxiliaryPidGetProc ( int  pid)

Definition at line 969 of file proc.c.

References AuxiliaryProcs, name, NUM_AUXILIARY_PROCS, PGPROC::pid, ProcQueueInit(), and ShmemInitStruct().

Referenced by pg_stat_get_activity().

970 {
971  PGPROC *result = NULL;
972  int index;
973 
974  if (pid == 0) /* never match dummy PGPROCs */
975  return NULL;
976 
977  for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
978  {
979  PGPROC *proc = &AuxiliaryProcs[index];
980 
981  if (proc->pid == pid)
982  {
983  result = proc;
984  break;
985  }
986  }
987  return result;
988 }
Definition: type.h:89
#define NUM_AUXILIARY_PROCS
Definition: proc.h:290
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:81
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ AuxiliaryProcKill()

static void AuxiliaryProcKill ( int  code,
Datum  arg 
)
static

Definition at line 922 of file proc.c.

References Assert, AuxiliaryProcs, ConditionVariableCancelSleep(), DatumGetInt32, DisownLatch(), LWLockReleaseAll(), MyProc, NUM_AUXILIARY_PROCS, PG_USED_FOR_ASSERTS_ONLY, PGPROC::pid, PGPROC::procLatch, ProcStructLock, SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, SwitchBackToLocalLatch(), and update_spins_per_delay().

Referenced by InitAuxiliaryProcess().

923 {
924  int proctype = DatumGetInt32(arg);
926  PGPROC *proc;
927 
928  Assert(proctype >= 0 && proctype < NUM_AUXILIARY_PROCS);
929 
930  auxproc = &AuxiliaryProcs[proctype];
931 
932  Assert(MyProc == auxproc);
933 
934  /* Release any LW locks I am holding (see notes above) */
936 
937  /* Cancel any pending condition variable sleep, too */
939 
940  /*
941  * Reset MyLatch to the process local one. This is so that signal
942  * handlers et al can continue using the latch after the shared latch
943  * isn't ours anymore. After that clear MyProc and disown the shared
944  * latch.
945  */
947  proc = MyProc;
948  MyProc = NULL;
949  DisownLatch(&proc->procLatch);
950 
952 
953  /* Mark auxiliary proc no longer in use */
954  proc->pid = 0;
955 
956  /* Update shared estimate of spins_per_delay */
958 
960 }
#define DatumGetInt32(X)
Definition: postgres.h:457
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:80
Latch procLatch
Definition: proc.h:104
#define SpinLockAcquire(lock)
Definition: spin.h:62
void SwitchBackToLocalLatch(void)
Definition: miscinit.c:361
void ConditionVariableCancelSleep(void)
int spins_per_delay
Definition: proc.h:267
#define NUM_AUXILIARY_PROCS
Definition: proc.h:290
int update_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:207
#define SpinLockRelease(lock)
Definition: spin.h:64
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
#define Assert(condition)
Definition: c.h:732
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:81
void DisownLatch(volatile Latch *latch)
Definition: latch.c:316
void * arg
void LWLockReleaseAll(void)
Definition: lwlock.c:1824
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:123
Definition: proc.h:95
int pid
Definition: proc.h:109

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 1834 of file proc.c.

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

Referenced by LaunchParallelWorkers().

1835 {
1836  LWLock *leader_lwlock;
1837 
1838  /* If we already did it, we don't need to do it again. */
1839  if (MyProc->lockGroupLeader == MyProc)
1840  return;
1841 
1842  /* We had better not be a follower. */
1843  Assert(MyProc->lockGroupLeader == NULL);
1844 
1845  /* Create single-member group, containing only ourselves. */
1846  leader_lwlock = LockHashPartitionLockByProc(MyProc);
1847  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1850  LWLockRelease(leader_lwlock);
1851 }
Definition: lwlock.h:32
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:300
dlist_head lockGroupMembers
Definition: proc.h:204
PGPROC * MyProc
Definition: proc.c:67
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
dlist_node lockGroupLink
Definition: proc.h:205
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:514
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
PGPROC * lockGroupLeader
Definition: proc.h:203

◆ BecomeLockGroupMember()

bool BecomeLockGroupMember ( PGPROC leader,
int  pid 
)

Definition at line 1864 of file proc.c.

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

Referenced by ParallelWorkerMain().

1865 {
1866  LWLock *leader_lwlock;
1867  bool ok = false;
1868 
1869  /* Group leader can't become member of group */
1870  Assert(MyProc != leader);
1871 
1872  /* Can't already be a member of a group */
1873  Assert(MyProc->lockGroupLeader == NULL);
1874 
1875  /* PID must be valid. */
1876  Assert(pid != 0);
1877 
1878  /*
1879  * Get lock protecting the group fields. Note LockHashPartitionLockByProc
1880  * accesses leader->pgprocno in a PGPROC that might be free. This is safe
1881  * because all PGPROCs' pgprocno fields are set during shared memory
1882  * initialization and never change thereafter; so we will acquire the
1883  * correct lock even if the leader PGPROC is in process of being recycled.
1884  */
1885  leader_lwlock = LockHashPartitionLockByProc(leader);
1886  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1887 
1888  /* Is this the leader we're looking for? */
1889  if (leader->pid == pid && leader->lockGroupLeader == leader)
1890  {
1891  /* OK, join the group */
1892  ok = true;
1893  MyProc->lockGroupLeader = leader;
1895  }
1896  LWLockRelease(leader_lwlock);
1897 
1898  return ok;
1899 }
Definition: lwlock.h:32
dlist_head lockGroupMembers
Definition: proc.h:204
PGPROC * MyProc
Definition: proc.c:67
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:317
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
dlist_node lockGroupLink
Definition: proc.h:205
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:514
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int pid
Definition: proc.h:109
PGPROC * lockGroupLeader
Definition: proc.h:203

◆ CheckDeadLock()

static void CheckDeadLock ( void  )
static

Definition at line 1674 of file proc.c.

References Assert, deadlock_state, DeadLockCheck(), DS_HARD_DEADLOCK, i, PGPROC::links, LockHashPartitionLockByIndex, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SHM_QUEUE::next, NUM_LOCK_PARTITIONS, SHM_QUEUE::prev, RemoveFromWaitQueue(), LOCK::tag, and PGPROC::waitLock.

Referenced by ProcSleep().

1675 {
1676  int i;
1677 
1678  /*
1679  * Acquire exclusive lock on the entire shared lock data structures. Must
1680  * grab LWLocks in partition-number order to avoid LWLock deadlock.
1681  *
1682  * Note that the deadlock check interrupt had better not be enabled
1683  * anywhere that this process itself holds lock partition locks, else this
1684  * will wait forever. Also note that LWLockAcquire creates a critical
1685  * section, so that this routine cannot be interrupted by cancel/die
1686  * interrupts.
1687  */
1688  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
1690 
1691  /*
1692  * Check to see if we've been awoken by anyone in the interim.
1693  *
1694  * If we have, we can return and resume our transaction -- happy day.
1695  * Before we are awoken the process releasing the lock grants it to us so
1696  * we know that we don't have to wait anymore.
1697  *
1698  * We check by looking to see if we've been unlinked from the wait queue.
1699  * This is quicker than checking our semaphore's state, since no kernel
1700  * call is needed, and it is safe because we hold the lock partition lock.
1701  */
1702  if (MyProc->links.prev == NULL ||
1703  MyProc->links.next == NULL)
1704  goto check_done;
1705 
1706 #ifdef LOCK_DEBUG
1707  if (Debug_deadlocks)
1708  DumpAllLocks();
1709 #endif
1710 
1711  /* Run the deadlock check, and set deadlock_state for use by ProcSleep */
1713 
1715  {
1716  /*
1717  * Oops. We have a deadlock.
1718  *
1719  * Get this process out of wait state. (Note: we could do this more
1720  * efficiently by relying on lockAwaited, but use this coding to
1721  * preserve the flexibility to kill some other transaction than the
1722  * one detecting the deadlock.)
1723  *
1724  * RemoveFromWaitQueue sets MyProc->waitStatus to STATUS_ERROR, so
1725  * ProcSleep will report an error after we return from the signal
1726  * handler.
1727  */
1728  Assert(MyProc->waitLock != NULL);
1730 
1731  /*
1732  * We're done here. Transaction abort caused by the error that
1733  * ProcSleep will raise will cause any other locks we hold to be
1734  * released, thus allowing other processes to wake up; we don't need
1735  * to do that here. NOTE: an exception is that releasing locks we
1736  * hold doesn't consider the possibility of waiters that were blocked
1737  * behind us on the lock we just failed to get, and might now be
1738  * wakable because we're not in front of them anymore. However,
1739  * RemoveFromWaitQueue took care of waking up any such processes.
1740  */
1741  }
1742 
1743  /*
1744  * And release locks. We do this in reverse order for two reasons: (1)
1745  * Anyone else who needs more than one of the locks will be trying to lock
1746  * them in increasing order; we don't want to release the other process
1747  * until it can get all the locks it needs. (2) This avoids O(N^2)
1748  * behavior inside LWLockRelease.
1749  */
1750 check_done:
1751  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
1753 }
PGPROC * MyProc
Definition: proc.c:67
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
LOCKTAG tag
Definition: lock.h:287
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
static DeadLockState deadlock_state
Definition: proc.c:87
DeadLockState DeadLockCheck(PGPROC *proc)
Definition: deadlock.c:217
LOCK * waitLock
Definition: proc.h:139
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1827
struct SHM_QUEUE * prev
Definition: shmem.h:30
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
int i
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117

◆ CheckDeadLockAlert()

void CheckDeadLockAlert ( void  )

Definition at line 1761 of file proc.c.

References got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres().

1762 {
1763  int save_errno = errno;
1764 
1765  got_deadlock_timeout = true;
1766 
1767  /*
1768  * Have to set the latch again, even if handle_sig_alarm already did. Back
1769  * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1770  * ever would be a problem, but setting a set latch again is cheap.
1771  */
1772  SetLatch(MyLatch);
1773  errno = save_errno;
1774 }
static volatile sig_atomic_t got_deadlock_timeout
Definition: proc.c:90
void SetLatch(volatile Latch *latch)
Definition: latch.c:436
struct Latch * MyLatch
Definition: globals.c:54

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 641 of file proc.c.

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery().

642 {
643  /* use volatile pointer to prevent code rearrangement */
644  volatile PROC_HDR *procglobal = ProcGlobal;
645 
646  return procglobal->startupBufferPinWaitBufId;
647 }
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: proc.h:244
int startupBufferPinWaitBufId
Definition: proc.h:272

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n)

Definition at line 655 of file proc.c.

References PROC_HDR::freeProcs, PGPROC::links, SHM_QUEUE::next, ProcStructLock, SpinLockAcquire, and SpinLockRelease.

Referenced by InitPostgres().

656 {
657  PGPROC *proc;
658 
660 
661  proc = ProcGlobal->freeProcs;
662 
663  while (n > 0 && proc != NULL)
664  {
665  proc = (PGPROC *) proc->links.next;
666  n--;
667  }
668 
670 
671  return (n <= 0);
672 }
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
PGPROC * freeProcs
Definition: proc.h:253
Definition: proc.h:95

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 499 of file proc.c.

References PROC_HDR::allPgXact, Assert, AuxiliaryProcKill(), AuxiliaryProcs, PGPROC::backendId, PGPROC::databaseId, PGXACT::delayChkpt, dlist_is_empty(), elog, ERROR, FATAL, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, i, Int32GetDatum, InvalidBackendId, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, IsBackgroundWorker, PGPROC::isBackgroundWorker, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, PGPROC::myProcLocks, MyProcPid, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, on_shmem_exit(), OwnLatch(), PANIC, PGPROC::pgprocno, PGSemaphoreReset(), PGPROC::pid, PGPROC::procLatch, ProcStructLock, PGPROC::roleId, PGPROC::sem, set_spins_per_delay(), SHMQueueElemInit(), SHMQueueEmpty(), SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, STATUS_OK, SwitchToSharedLatch(), PGPROC::tempNamespaceId, PGXACT::vacuumFlags, PGPROC::waitLock, PGPROC::waitProcLock, PGPROC::waitStatus, PGXACT::xid, and PGXACT::xmin.

Referenced by AuxiliaryProcessMain(), and BackendRun().

500 {
501  PGPROC *auxproc;
502  int proctype;
503 
504  /*
505  * ProcGlobal should be set up already (if we are a backend, we inherit
506  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
507  */
508  if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
509  elog(PANIC, "proc header uninitialized");
510 
511  if (MyProc != NULL)
512  elog(ERROR, "you already exist");
513 
514  /*
515  * We use the ProcStructLock to protect assignment and releasing of
516  * AuxiliaryProcs entries.
517  *
518  * While we are holding the ProcStructLock, also copy the current shared
519  * estimate of spins_per_delay to local storage.
520  */
522 
524 
525  /*
526  * Find a free auxproc ... *big* trouble if there isn't one ...
527  */
528  for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
529  {
530  auxproc = &AuxiliaryProcs[proctype];
531  if (auxproc->pid == 0)
532  break;
533  }
534  if (proctype >= NUM_AUXILIARY_PROCS)
535  {
537  elog(FATAL, "all AuxiliaryProcs are in use");
538  }
539 
540  /* Mark auxiliary proc as in use by me */
541  /* use volatile pointer to prevent code rearrangement */
542  ((volatile PGPROC *) auxproc)->pid = MyProcPid;
543 
544  MyProc = auxproc;
545  MyPgXact = &ProcGlobal->allPgXact[auxproc->pgprocno];
546 
548 
549  /*
550  * Initialize all fields of MyProc, except for those previously
551  * initialized by InitProcGlobal.
552  */
556  MyProc->fpVXIDLock = false;
565  MyPgXact->delayChkpt = false;
566  MyPgXact->vacuumFlags = 0;
567  MyProc->lwWaiting = false;
568  MyProc->lwWaitMode = 0;
569  MyProc->waitLock = NULL;
570  MyProc->waitProcLock = NULL;
571 #ifdef USE_ASSERT_CHECKING
572  {
573  int i;
574 
575  /* Last process should have released all locks. */
576  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
578  }
579 #endif
580 
581  /*
582  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
583  * on it. That allows us to repoint the process latch, which so far
584  * points to process local one, to the shared one.
585  */
588 
589  /* Check that group locking fields are in a proper initial state. */
590  Assert(MyProc->lockGroupLeader == NULL);
592 
593  /*
594  * We might be reusing a semaphore that belonged to a failed process. So
595  * be careful and reinitialize its value here. (This is not strictly
596  * necessary anymore, but seems like a good idea for cleanliness.)
597  */
599 
600  /*
601  * Arrange to clean up at process exit.
602  */
604 }
static void AuxiliaryProcKill(int code, Datum arg)
Definition: proc.c:922
void set_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:196
int MyProcPid
Definition: globals.c:40
BackendId backendId
Definition: proc.h:113
dlist_head lockGroupMembers
Definition: proc.h:204
Oid tempNamespaceId
Definition: proc.h:117
TransactionId xmin
Definition: proc.h:228
PGXACT * allPgXact
Definition: proc.h:249
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:224
SHM_QUEUE links
Definition: proc.h:98
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:284
bool lwWaiting
Definition: proc.h:130
Oid roleId
Definition: proc.h:115
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 lwWaitMode
Definition: proc.h:131
bool fpVXIDLock
Definition: proc.h:195
#define PANIC
Definition: elog.h:53
Latch procLatch
Definition: proc.h:104
PGXACT * MyPgXact
Definition: proc.c:68
uint8 vacuumFlags
Definition: proc.h:233
bool IsBackgroundWorker
Definition: globals.c:111
bool isBackgroundWorker
Definition: proc.h:120
#define SpinLockAcquire(lock)
Definition: spin.h:62
int spins_per_delay
Definition: proc.h:267
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
PROCLOCK * waitProcLock
Definition: proc.h:140
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
#define InvalidTransactionId
Definition: transam.h:31
Oid databaseId
Definition: proc.h:114
void OwnLatch(volatile Latch *latch)
Definition: latch.c:296
LOCK * waitLock
Definition: proc.h:139
#define NUM_AUXILIARY_PROCS
Definition: proc.h:290
#define STATUS_OK
Definition: c.h:1075
bool delayChkpt
Definition: proc.h:235
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define SpinLockRelease(lock)
Definition: spin.h:64
#define InvalidBackendId
Definition: backendid.h:23
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
void SwitchToSharedLatch(void)
Definition: miscinit.c:342
int waitStatus
Definition: proc.h:102
#define InvalidOid
Definition: postgres_ext.h:36
#define Assert(condition)
Definition: c.h:732
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:81
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
#define Int32GetDatum(X)
Definition: postgres.h:464
int pgprocno
Definition: proc.h:110
#define elog(elevel,...)
Definition: elog.h:226
#define InvalidLocalTransactionId
Definition: lock.h:69
int i
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
PGSemaphore sem
Definition: proc.h:101
Definition: proc.h:95
int pid
Definition: proc.h:109
PGPROC * lockGroupLeader
Definition: proc.h:203
LocalTransactionId fpLocalTransactionId
Definition: proc.h:196
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
LocalTransactionId lxid
Definition: proc.h:106

◆ InitProcess()

void InitProcess ( void  )

Definition at line 295 of file proc.c.

References PROC_HDR::allPgXact, Assert, PROC_HDR::autovacFreeProcs, PGPROC::backendId, PROC_HDR::bgworkerFreeProcs, PGPROC::clogGroupMember, PGPROC::clogGroupMemberLsn, PGPROC::clogGroupMemberPage, PGPROC::clogGroupMemberXid, PGPROC::clogGroupMemberXidStatus, PGPROC::clogGroupNext, PGPROC::databaseId, PGXACT::delayChkpt, dlist_is_empty(), elog, ereport, errcode(), errmsg(), ERROR, FATAL, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, PROC_HDR::freeProcs, i, InitDeadLockChecking(), InitLWLockAccess(), INVALID_PGPROCNO, InvalidBackendId, InvalidLocalTransactionId, InvalidOid, InvalidTransactionId, InvalidXLogRecPtr, IsAnyAutoVacuumProcess, IsAutoVacuumLauncherProcess(), IsAutoVacuumWorkerProcess(), IsBackgroundWorker, PGPROC::isBackgroundWorker, IsUnderPostmaster, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, MarkPostmasterChildActive(), PGPROC::myProcLocks, MyProcPid, SHM_QUEUE::next, NUM_LOCK_PARTITIONS, on_shmem_exit(), OwnLatch(), PANIC, pg_atomic_read_u32(), PGPROC::pgprocno, PGSemaphoreReset(), PGPROC::pid, PROC_IS_AUTOVACUUM, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, PGPROC::procgloballist, ProcKill(), PGPROC::procLatch, ProcStructLock, PGPROC::recoveryConflictPending, PGPROC::roleId, PGPROC::sem, set_spins_per_delay(), SHMQueueElemInit(), SHMQueueEmpty(), SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, STATUS_OK, SwitchToSharedLatch(), SYNC_REP_NOT_WAITING, PGPROC::syncRepLinks, PGPROC::syncRepState, PGPROC::tempNamespaceId, TRANSACTION_STATUS_IN_PROGRESS, PGXACT::vacuumFlags, PGPROC::wait_event_info, PGPROC::waitLock, PGPROC::waitLSN, PGPROC::waitProcLock, PGPROC::waitStatus, PGXACT::xid, and PGXACT::xmin.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackendRun(), BootstrapModeMain(), PostgresMain(), and StartBackgroundWorker().

296 {
297  PGPROC *volatile *procgloballist;
298 
299  /*
300  * ProcGlobal should be set up already (if we are a backend, we inherit
301  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
302  */
303  if (ProcGlobal == NULL)
304  elog(PANIC, "proc header uninitialized");
305 
306  if (MyProc != NULL)
307  elog(ERROR, "you already exist");
308 
309  /* Decide which list should supply our PGPROC. */
311  procgloballist = &ProcGlobal->autovacFreeProcs;
312  else if (IsBackgroundWorker)
313  procgloballist = &ProcGlobal->bgworkerFreeProcs;
314  else
315  procgloballist = &ProcGlobal->freeProcs;
316 
317  /*
318  * Try to get a proc struct from the appropriate free list. If this
319  * fails, we must be out of PGPROC structures (not to mention semaphores).
320  *
321  * While we are holding the ProcStructLock, also copy the current shared
322  * estimate of spins_per_delay to local storage.
323  */
325 
327 
328  MyProc = *procgloballist;
329 
330  if (MyProc != NULL)
331  {
332  *procgloballist = (PGPROC *) MyProc->links.next;
334  }
335  else
336  {
337  /*
338  * If we reach here, all the PGPROCs are in use. This is one of the
339  * possible places to detect "too many backends", so give the standard
340  * error message. XXX do we need to give a different failure message
341  * in the autovacuum case?
342  */
344  ereport(FATAL,
345  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
346  errmsg("sorry, too many clients already")));
347  }
349 
350  /*
351  * Cross-check that the PGPROC is of the type we expect; if this were not
352  * the case, it would get returned to the wrong list.
353  */
354  Assert(MyProc->procgloballist == procgloballist);
355 
356  /*
357  * Now that we have a PGPROC, mark ourselves as an active postmaster
358  * child; this is so that the postmaster can detect it if we exit without
359  * cleaning up. (XXX autovac launcher currently doesn't participate in
360  * this; it probably should.)
361  */
364 
365  /*
366  * Initialize all fields of MyProc, except for those previously
367  * initialized by InitProcGlobal.
368  */
372  MyProc->fpVXIDLock = false;
376  MyProc->pid = MyProcPid;
377  /* backendId, databaseId and roleId will be filled in later */
383  MyPgXact->delayChkpt = false;
384  MyPgXact->vacuumFlags = 0;
385  /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
388  MyProc->lwWaiting = false;
389  MyProc->lwWaitMode = 0;
390  MyProc->waitLock = NULL;
391  MyProc->waitProcLock = NULL;
392 #ifdef USE_ASSERT_CHECKING
393  {
394  int i;
395 
396  /* Last process should have released all locks. */
397  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
399  }
400 #endif
402 
403  /* Initialize fields for sync rep */
404  MyProc->waitLSN = 0;
407 
408  /* Initialize fields for group XID clearing. */
409  MyProc->procArrayGroupMember = false;
412 
413  /* Check that group locking fields are in a proper initial state. */
414  Assert(MyProc->lockGroupLeader == NULL);
416 
417  /* Initialize wait event information. */
418  MyProc->wait_event_info = 0;
419 
420  /* Initialize fields for group transaction status update. */
421  MyProc->clogGroupMember = false;
427 
428  /*
429  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
430  * on it. That allows us to repoint the process latch, which so far
431  * points to process local one, to the shared one.
432  */
435 
436  /*
437  * We might be reusing a semaphore that belonged to a failed process. So
438  * be careful and reinitialize its value here. (This is not strictly
439  * necessary anymore, but seems like a good idea for cleanliness.)
440  */
442 
443  /*
444  * Arrange to clean up at backend exit.
445  */
447 
448  /*
449  * Now that we have a PGPROC, we could try to acquire locks, so initialize
450  * local state needed for LWLocks, and the deadlock checker.
451  */
454 }
bool procArrayGroupMember
Definition: proc.h:166
static void ProcKill(int code, Datum arg)
Definition: proc.c:799
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XidStatus clogGroupMemberXidStatus
Definition: proc.h:182
void set_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:196
int MyProcPid
Definition: globals.c:40
BackendId backendId
Definition: proc.h:113
uint32 wait_event_info
Definition: proc.h:176
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:186
dlist_head lockGroupMembers
Definition: proc.h:204
Oid tempNamespaceId
Definition: proc.h:117
TransactionId xmin
Definition: proc.h:228
PGXACT * allPgXact
Definition: proc.h:249
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:224
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:284
bool lwWaiting
Definition: proc.h:130
#define SYNC_REP_NOT_WAITING
Definition: syncrep.h:31
PGPROC * bgworkerFreeProcs
Definition: proc.h:257
Oid roleId
Definition: proc.h:115
int errcode(int sqlerrcode)
Definition: elog.c:570
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 lwWaitMode
Definition: proc.h:131
pg_atomic_uint32 clogGroupNext
Definition: proc.h:180
bool fpVXIDLock
Definition: proc.h:195
#define PANIC
Definition: elog.h:53
PGPROC * autovacFreeProcs
Definition: proc.h:255
Latch procLatch
Definition: proc.h:104
PGXACT * MyPgXact
Definition: proc.c:68
uint8 vacuumFlags
Definition: proc.h:233
bool IsBackgroundWorker
Definition: globals.c:111
bool isBackgroundWorker
Definition: proc.h:120
#define SpinLockAcquire(lock)
Definition: spin.h:62
int spins_per_delay
Definition: proc.h:267
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
PROCLOCK * waitProcLock
Definition: proc.h:140
void InitDeadLockChecking(void)
Definition: deadlock.c:143
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
int clogGroupMemberPage
Definition: proc.h:184
bool recoveryConflictPending
Definition: proc.h:127
bool IsUnderPostmaster
Definition: globals.c:109
#define InvalidTransactionId
Definition: transam.h:31
TransactionId clogGroupMemberXid
Definition: proc.h:181
Oid databaseId
Definition: proc.h:114
PGPROC ** procgloballist
Definition: proc.h:99
void OwnLatch(volatile Latch *latch)
Definition: latch.c:296
LOCK * waitLock
Definition: proc.h:139
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3277
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1075
bool delayChkpt
Definition: proc.h:235
#define INVALID_PGPROCNO
Definition: proc.h:77
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:168
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define SpinLockRelease(lock)
Definition: spin.h:64
#define InvalidBackendId
Definition: backendid.h:23
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
void SwitchToSharedLatch(void)
Definition: miscinit.c:342
int waitStatus
Definition: proc.h:102
#define InvalidOid
Definition: postgres_ext.h:36
#define IsAnyAutoVacuumProcess()
Definition: autovacuum.h:53
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3271
#define Assert(condition)
Definition: c.h:732
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
PGPROC * freeProcs
Definition: proc.h:253
SHM_QUEUE syncRepLinks
Definition: proc.h:153
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
int pgprocno
Definition: proc.h:110
int errmsg(const char *fmt,...)
Definition: elog.c:784
bool clogGroupMember
Definition: proc.h:179
#define elog(elevel,...)
Definition: elog.h:226
#define InvalidLocalTransactionId
Definition: lock.h:69
int i
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
PGSemaphore sem
Definition: proc.h:101
int syncRepState
Definition: proc.h:152
Definition: proc.h:95
int pid
Definition: proc.h:109
XLogRecPtr waitLSN
Definition: proc.h:151
PGPROC * lockGroupLeader
Definition: proc.h:203
LocalTransactionId fpLocalTransactionId
Definition: proc.h:196
#define PROC_IS_AUTOVACUUM
Definition: proc.h:53
TransactionId procArrayGroupMemberXid
Definition: proc.h:174
void InitLWLockAccess(void)
Definition: lwlock.c:535
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:26
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:244
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:256
LocalTransactionId lxid
Definition: proc.h:106

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 464 of file proc.c.

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

Referenced by InitPostgres().

465 {
466  Assert(MyProc != NULL);
467 
468  /*
469  * Add our PGPROC to the PGPROC array in shared memory.
470  */
472 
473  /*
474  * Arrange to clean that up at backend exit.
475  */
477 }
static void RemoveProcFromArray(int code, Datum arg)
Definition: proc.c:788
PGPROC * MyProc
Definition: proc.c:67
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
#define Assert(condition)
Definition: c.h:732
void ProcArrayAdd(PGPROC *proc)
Definition: procarray.c:276

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 162 of file proc.c.

References PROC_HDR::allPgXact, PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert, PROC_HDR::autovacFreeProcs, autovacuum_max_workers, AuxiliaryProcs, PROC_HDR::bgworkerFreeProcs, PROC_HDR::checkpointerLatch, PROC_HDR::clogGroupFirst, DEFAULT_SPINS_PER_DELAY, dlist_init(), PROC_HDR::freeProcs, i, InitSharedLatch(), INVALID_PGPROCNO, PGPROC::links, LWLockInitialize(), LWTRANCHE_PROC, max_prepared_xacts, MaxBackends, MaxConnections, MemSet, SHM_QUEUE::next, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, pg_atomic_init_u32(), PGPROC::pgprocno, PGSemaphoreCreate(), PROC_HDR::procArrayGroupFirst, PGPROC::procgloballist, ProcStructLock, PGPROC::sem, ShmemAlloc(), ShmemInitStruct(), SHMQueueInit(), SpinLockInit, PROC_HDR::spins_per_delay, PROC_HDR::startupBufferPinWaitBufId, PROC_HDR::startupProc, PROC_HDR::startupProcPid, and PROC_HDR::walwriterLatch.

Referenced by CreateSharedMemoryAndSemaphores().

163 {
164  PGPROC *procs;
165  PGXACT *pgxacts;
166  int i,
167  j;
168  bool found;
170 
171  /* Create the ProcGlobal shared structure */
172  ProcGlobal = (PROC_HDR *)
173  ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
174  Assert(!found);
175 
176  /*
177  * Initialize the data structures.
178  */
180  ProcGlobal->freeProcs = NULL;
183  ProcGlobal->startupProc = NULL;
186  ProcGlobal->walwriterLatch = NULL;
190 
191  /*
192  * Create and initialize all the PGPROC structures we'll need. There are
193  * five separate consumers: (1) normal backends, (2) autovacuum workers
194  * and the autovacuum launcher, (3) background workers, (4) auxiliary
195  * processes, and (5) prepared transactions. Each PGPROC structure is
196  * dedicated to exactly one of these purposes, and they do not move
197  * between groups.
198  */
199  procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
200  MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
201  ProcGlobal->allProcs = procs;
202  /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
204 
205  /*
206  * Also allocate a separate array of PGXACT structures. This is separate
207  * from the main PGPROC array so that the most heavily accessed data is
208  * stored contiguously in memory in as few cache lines as possible. This
209  * provides significant performance benefits, especially on a
210  * multiprocessor system. There is one PGXACT structure for every PGPROC
211  * structure.
212  */
213  pgxacts = (PGXACT *) ShmemAlloc(TotalProcs * sizeof(PGXACT));
214  MemSet(pgxacts, 0, TotalProcs * sizeof(PGXACT));
215  ProcGlobal->allPgXact = pgxacts;
216 
217  for (i = 0; i < TotalProcs; i++)
218  {
219  /* Common initialization for all PGPROCs, regardless of type. */
220 
221  /*
222  * Set up per-PGPROC semaphore, latch, and backendLock. Prepared xact
223  * dummy PGPROCs don't need these though - they're never associated
224  * with a real process
225  */
226  if (i < MaxBackends + NUM_AUXILIARY_PROCS)
227  {
228  procs[i].sem = PGSemaphoreCreate();
229  InitSharedLatch(&(procs[i].procLatch));
230  LWLockInitialize(&(procs[i].backendLock), LWTRANCHE_PROC);
231  }
232  procs[i].pgprocno = i;
233 
234  /*
235  * Newly created PGPROCs for normal backends, autovacuum and bgworkers
236  * must be queued up on the appropriate free list. Because there can
237  * only ever be a small, fixed number of auxiliary processes, no free
238  * list is used in that case; InitAuxiliaryProcess() instead uses a
239  * linear search. PGPROCs for prepared transactions are added to a
240  * free list by TwoPhaseShmemInit().
241  */
242  if (i < MaxConnections)
243  {
244  /* PGPROC for normal backend, add to freeProcs list */
245  procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs;
246  ProcGlobal->freeProcs = &procs[i];
247  procs[i].procgloballist = &ProcGlobal->freeProcs;
248  }
249  else if (i < MaxConnections + autovacuum_max_workers + 1)
250  {
251  /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */
253  ProcGlobal->autovacFreeProcs = &procs[i];
255  }
256  else if (i < MaxBackends)
257  {
258  /* PGPROC for bgworker, add to bgworkerFreeProcs list */
260  ProcGlobal->bgworkerFreeProcs = &procs[i];
262  }
263 
264  /* Initialize myProcLocks[] shared memory queues. */
265  for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
266  SHMQueueInit(&(procs[i].myProcLocks[j]));
267 
268  /* Initialize lockGroupMembers list. */
269  dlist_init(&procs[i].lockGroupMembers);
270 
271  /*
272  * Initialize the atomic variables, otherwise, it won't be safe to
273  * access them for backends that aren't currently in use.
274  */
275  pg_atomic_init_u32(&(procs[i].procArrayGroupNext), INVALID_PGPROCNO);
276  pg_atomic_init_u32(&(procs[i].clogGroupNext), INVALID_PGPROCNO);
277  }
278 
279  /*
280  * Save pointers to the blocks of PGPROC structures reserved for auxiliary
281  * processes and prepared transactions.
282  */
283  AuxiliaryProcs = &procs[MaxBackends];
285 
286  /* Create ProcStructLock spinlock, too */
287  ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
289 }
int slock_t
Definition: s_lock.h:912
Definition: proc.h:222
PGXACT * allPgXact
Definition: proc.h:249
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
#define SpinLockInit(lock)
Definition: spin.h:60
PGPROC * PreparedXactProcs
Definition: proc.c:82
PGPROC * bgworkerFreeProcs
Definition: proc.h:257
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define MemSet(start, val, len)
Definition: c.h:941
void * ShmemAlloc(Size size)
Definition: shmem.c:157
PGSemaphore PGSemaphoreCreate(void)
Definition: posix_sema.c:251
PGPROC * autovacFreeProcs
Definition: proc.h:255
Latch * walwriterLatch
Definition: proc.h:263
int spins_per_delay
Definition: proc.h:267
int max_prepared_xacts
Definition: twophase.c:117
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
int MaxBackends
Definition: globals.c:135
unsigned int uint32
Definition: c.h:358
PGPROC ** procgloballist
Definition: proc.h:99
#define NUM_AUXILIARY_PROCS
Definition: proc.h:290
#define INVALID_PGPROCNO
Definition: proc.h:77
Definition: proc.h:244
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:677
int startupProcPid
Definition: proc.h:270
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
int MaxConnections
Definition: globals.c:132
int autovacuum_max_workers
Definition: autovacuum.c:114
static void dlist_init(dlist_head *head)
Definition: ilist.h:278
Latch * checkpointerLatch
Definition: proc.h:265
#define Assert(condition)
Definition: c.h:732
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:81
PGPROC * freeProcs
Definition: proc.h:253
uint32 allProcCount
Definition: proc.h:251
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:261
int pgprocno
Definition: proc.h:110
pg_atomic_uint32 procArrayGroupFirst
Definition: proc.h:259
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int startupBufferPinWaitBufId
Definition: proc.h:272
int i
PGPROC * allProcs
Definition: proc.h:247
PGPROC * startupProc
Definition: proc.h:269
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:226
PGSemaphore sem
Definition: proc.h:101
void InitSharedLatch(volatile Latch *latch)
Definition: latch.c:260
Definition: proc.h:95
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
#define DEFAULT_SPINS_PER_DELAY
Definition: s_lock.h:990

◆ IsWaitingForLock()

bool IsWaitingForLock ( void  )

Definition at line 678 of file proc.c.

Referenced by RecoveryConflictInterrupt().

679 {
680  if (lockAwaited == NULL)
681  return false;
682 
683  return true;
684 }
static LOCALLOCK * lockAwaited
Definition: proc.c:85

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 695 of file proc.c.

References AbortStrongLockAcquire(), DEADLOCK_TIMEOUT, disable_timeouts(), GrantAwaitedLock(), LOCALLOCK::hashcode, HOLD_INTERRUPTS, DisableTimeoutParams::id, DisableTimeoutParams::keep_indicator, PGPROC::links, LOCK_TIMEOUT, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SHM_QUEUE::next, RemoveFromWaitQueue(), RESUME_INTERRUPTS, STATUS_OK, and PGPROC::waitStatus.

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

696 {
697  LWLock *partitionLock;
698  DisableTimeoutParams timeouts[2];
699 
700  HOLD_INTERRUPTS();
701 
703 
704  /* Nothing to do if we weren't waiting for a lock */
705  if (lockAwaited == NULL)
706  {
708  return;
709  }
710 
711  /*
712  * Turn off the deadlock and lock timeout timers, if they are still
713  * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
714  * indicator flag, since this function is executed before
715  * ProcessInterrupts when responding to SIGINT; else we'd lose the
716  * knowledge that the SIGINT came from a lock timeout and not an external
717  * source.
718  */
719  timeouts[0].id = DEADLOCK_TIMEOUT;
720  timeouts[0].keep_indicator = false;
721  timeouts[1].id = LOCK_TIMEOUT;
722  timeouts[1].keep_indicator = true;
723  disable_timeouts(timeouts, 2);
724 
725  /* Unlink myself from the wait queue, if on it (might not be anymore!) */
726  partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
727  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
728 
729  if (MyProc->links.next != NULL)
730  {
731  /* We could not have been granted the lock yet */
733  }
734  else
735  {
736  /*
737  * Somebody kicked us off the lock queue already. Perhaps they
738  * granted us the lock, or perhaps they detected a deadlock. If they
739  * did grant us the lock, we'd better remember it in our local lock
740  * table.
741  */
742  if (MyProc->waitStatus == STATUS_OK)
744  }
745 
746  lockAwaited = NULL;
747 
748  LWLockRelease(partitionLock);
749 
751 }
uint32 hashcode
Definition: lock.h:409
Definition: lwlock.h:32
void GrantAwaitedLock(void)
Definition: lock.c:1695
PGPROC * MyProc
Definition: proc.c:67
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
void disable_timeouts(const DisableTimeoutParams *timeouts, int count)
Definition: timeout.c:561
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:118
TimeoutId id
Definition: timeout.h:65
void AbortStrongLockAcquire(void)
Definition: lock.c:1666
#define STATUS_OK
Definition: c.h:1075
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1827
int waitStatus
Definition: proc.h:102
static LOCALLOCK * lockAwaited
Definition: proc.c:85
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:116

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 128 of file proc.c.

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CreateSharedMemoryAndSemaphores().

129 {
130  /*
131  * We need a sema per backend (including autovacuum), plus one for each
132  * auxiliary process.
133  */
135 }
int MaxBackends
Definition: globals.c:135
#define NUM_AUXILIARY_PROCS
Definition: proc.h:290

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 102 of file proc.c.

References add_size(), max_prepared_xacts, MaxBackends, mul_size(), and NUM_AUXILIARY_PROCS.

Referenced by CreateSharedMemoryAndSemaphores().

103 {
104  Size size = 0;
105 
106  /* ProcGlobal */
107  size = add_size(size, sizeof(PROC_HDR));
108  /* MyProcs, including autovacuum workers and launcher */
109  size = add_size(size, mul_size(MaxBackends, sizeof(PGPROC)));
110  /* AuxiliaryProcs */
111  size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGPROC)));
112  /* Prepared xacts */
113  size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGPROC)));
114  /* ProcStructLock */
115  size = add_size(size, sizeof(slock_t));
116 
117  size = add_size(size, mul_size(MaxBackends, sizeof(PGXACT)));
118  size = add_size(size, mul_size(NUM_AUXILIARY_PROCS, sizeof(PGXACT)));
119  size = add_size(size, mul_size(max_prepared_xacts, sizeof(PGXACT)));
120 
121  return size;
122 }
int slock_t
Definition: s_lock.h:912
Definition: proc.h:222
int max_prepared_xacts
Definition: twophase.c:117
int MaxBackends
Definition: globals.c:135
#define NUM_AUXILIARY_PROCS
Definition: proc.h:290
Definition: proc.h:244
Size mul_size(Size s1, Size s2)
Definition: shmem.c:492
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:466
Definition: proc.h:95

◆ ProcKill()

static void ProcKill ( int  code,
Datum  arg 
)
static

Definition at line 799 of file proc.c.

References Assert, AutovacuumLauncherPid, ConditionVariableCancelSleep(), DisownLatch(), dlist_delete(), dlist_is_empty(), i, IsAutoVacuumLauncherProcess(), IsUnderPostmaster, kill, PGPROC::links, PGPROC::lockGroupLeader, PGPROC::lockGroupLink, PGPROC::lockGroupMembers, LockHashPartitionLockByProc, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LWLockReleaseAll(), MarkPostmasterChildInactive(), MyProc, PGPROC::myProcLocks, MyReplicationSlot, SHM_QUEUE::next, NUM_LOCK_PARTITIONS, PGPROC::procgloballist, PGPROC::procLatch, ProcStructLock, ReplicationSlotCleanup(), ReplicationSlotRelease(), SHMQueueEmpty(), SIGUSR2, SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, SwitchBackToLocalLatch(), SyncRepCleanupAtProcExit(), and update_spins_per_delay().

Referenced by InitProcess().

800 {
801  PGPROC *proc;
802  PGPROC *volatile *procgloballist;
803 
804  Assert(MyProc != NULL);
805 
806  /* Make sure we're out of the sync rep lists */
808 
809 #ifdef USE_ASSERT_CHECKING
810  {
811  int i;
812 
813  /* Last process should have released all locks. */
814  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
816  }
817 #endif
818 
819  /*
820  * Release any LW locks I am holding. There really shouldn't be any, but
821  * it's cheap to check again before we cut the knees off the LWLock
822  * facility by releasing our PGPROC ...
823  */
825 
826  /* Cancel any pending condition variable sleep, too */
828 
829  /* Make sure active replication slots are released */
830  if (MyReplicationSlot != NULL)
832 
833  /* Also cleanup all the temporary slots. */
835 
836  /*
837  * Detach from any lock group of which we are a member. If the leader
838  * exist before all other group members, it's PGPROC will remain allocated
839  * until the last group process exits; that process must return the
840  * leader's PGPROC to the appropriate list.
841  */
842  if (MyProc->lockGroupLeader != NULL)
843  {
844  PGPROC *leader = MyProc->lockGroupLeader;
845  LWLock *leader_lwlock = LockHashPartitionLockByProc(leader);
846 
847  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
850  if (dlist_is_empty(&leader->lockGroupMembers))
851  {
852  leader->lockGroupLeader = NULL;
853  if (leader != MyProc)
854  {
855  procgloballist = leader->procgloballist;
856 
857  /* Leader exited first; return its PGPROC. */
859  leader->links.next = (SHM_QUEUE *) *procgloballist;
860  *procgloballist = leader;
862  }
863  }
864  else if (leader != MyProc)
865  MyProc->lockGroupLeader = NULL;
866  LWLockRelease(leader_lwlock);
867  }
868 
869  /*
870  * Reset MyLatch to the process local one. This is so that signal
871  * handlers et al can continue using the latch after the shared latch
872  * isn't ours anymore. After that clear MyProc and disown the shared
873  * latch.
874  */
876  proc = MyProc;
877  MyProc = NULL;
878  DisownLatch(&proc->procLatch);
879 
880  procgloballist = proc->procgloballist;
882 
883  /*
884  * If we're still a member of a locking group, that means we're a leader
885  * which has somehow exited before its children. The last remaining child
886  * will release our PGPROC. Otherwise, release it now.
887  */
888  if (proc->lockGroupLeader == NULL)
889  {
890  /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
892 
893  /* Return PGPROC structure (and semaphore) to appropriate freelist */
894  proc->links.next = (SHM_QUEUE *) *procgloballist;
895  *procgloballist = proc;
896  }
897 
898  /* Update shared estimate of spins_per_delay */
900 
902 
903  /*
904  * This process is no longer present in shared memory in any meaningful
905  * way, so tell the postmaster we've cleaned up acceptably well. (XXX
906  * autovac launcher should be included here someday)
907  */
910 
911  /* wake autovac launcher if needed -- see comments in FreeWorkerInfo */
912  if (AutovacuumLauncherPid != 0)
914 }
Definition: lwlock.h:32
dlist_head lockGroupMembers
Definition: proc.h:204
PGPROC * MyProc
Definition: proc.c:67
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
PROC_HDR * ProcGlobal
Definition: proc.c:80
void MarkPostmasterChildInactive(void)
Definition: pmsignal.c:289
#define kill(pid, sig)
Definition: win32_port.h:435
#define SIGUSR2
Definition: win32_port.h:176
Latch procLatch
Definition: proc.h:104
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SpinLockAcquire(lock)
Definition: spin.h:62
void SwitchBackToLocalLatch(void)
Definition: miscinit.c:361
dlist_node lockGroupLink
Definition: proc.h:205
void ConditionVariableCancelSleep(void)
int spins_per_delay
Definition: proc.h:267
int AutovacuumLauncherPid
Definition: autovacuum.c:305
bool IsUnderPostmaster
Definition: globals.c:109
void ReplicationSlotRelease(void)
Definition: slot.c:424
PGPROC ** procgloballist
Definition: proc.h:99
static void dlist_delete(dlist_node *node)
Definition: ilist.h:358
int update_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:207
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:514
#define SpinLockRelease(lock)
Definition: spin.h:64
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3271
ReplicationSlot * MyReplicationSlot
Definition: slot.c:96
#define Assert(condition)
Definition: c.h:732
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:289
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void SyncRepCleanupAtProcExit(void)
Definition: syncrep.c:363
void DisownLatch(volatile Latch *latch)
Definition: latch.c:316
int i
void ReplicationSlotCleanup(void)
Definition: slot.c:479
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
void LWLockReleaseAll(void)
Definition: lwlock.c:1824
Definition: proc.h:95
PGPROC * lockGroupLeader
Definition: proc.h:203
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117

◆ ProcLockWakeup()

void ProcLockWakeup ( LockMethod  lockMethodTable,
LOCK lock 
)

Definition at line 1613 of file proc.c.

References Assert, LockMethodData::conflictTab, GrantLock(), PROC_QUEUE::links, PGPROC::links, LOCKBIT_ON, LockCheckConflicts(), SHM_QUEUE::next, ProcWakeup(), PROC_QUEUE::size, STATUS_OK, PGPROC::waitLockMode, PGPROC::waitProcLock, and LOCK::waitProcs.

Referenced by CleanUpLock(), and DeadLockCheck().

1614 {
1615  PROC_QUEUE *waitQueue = &(lock->waitProcs);
1616  int queue_size = waitQueue->size;
1617  PGPROC *proc;
1618  LOCKMASK aheadRequests = 0;
1619 
1620  Assert(queue_size >= 0);
1621 
1622  if (queue_size == 0)
1623  return;
1624 
1625  proc = (PGPROC *) waitQueue->links.next;
1626 
1627  while (queue_size-- > 0)
1628  {
1629  LOCKMODE lockmode = proc->waitLockMode;
1630 
1631  /*
1632  * Waken if (a) doesn't conflict with requests of earlier waiters, and
1633  * (b) doesn't conflict with already-held locks.
1634  */
1635  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1636  LockCheckConflicts(lockMethodTable,
1637  lockmode,
1638  lock,
1639  proc->waitProcLock) == STATUS_OK)
1640  {
1641  /* OK to waken */
1642  GrantLock(lock, proc->waitProcLock, lockmode);
1643  proc = ProcWakeup(proc, STATUS_OK);
1644 
1645  /*
1646  * ProcWakeup removes proc from the lock's waiting process queue
1647  * and returns the next proc in chain; don't use proc's next-link,
1648  * because it's been cleared.
1649  */
1650  }
1651  else
1652  {
1653  /*
1654  * Cannot wake this guy. Remember his request for later checks.
1655  */
1656  aheadRequests |= LOCKBIT_ON(lockmode);
1657  proc = (PGPROC *) proc->links.next;
1658  }
1659  }
1660 
1661  Assert(waitQueue->size >= 0);
1662 }
int LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1344
int LOCKMODE
Definition: lockdefs.h:26
SHM_QUEUE links
Definition: lock.h:32
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1467
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
LOCKMODE waitLockMode
Definition: proc.h:141
const LOCKMASK * conflictTab
Definition: lock.h:114
PROC_QUEUE waitProcs
Definition: lock.h:293
PROCLOCK * waitProcLock
Definition: proc.h:140
#define STATUS_OK
Definition: c.h:1075
#define Assert(condition)
Definition: c.h:732
int LOCKMASK
Definition: lockdefs.h:25
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
int size
Definition: lock.h:33
PGPROC * ProcWakeup(PGPROC *proc, int waitStatus)
Definition: proc.c:1577
Definition: proc.h:95

◆ ProcQueueInit()

void ProcQueueInit ( PROC_QUEUE queue)

Definition at line 1022 of file proc.c.

References PROC_QUEUE::links, SHMQueueInit(), and PROC_QUEUE::size.

Referenced by AuxiliaryPidGetProc(), DeadLockCheck(), lock_twophase_recover(), and SetupLockInTable().

1023 {
1024  SHMQueueInit(&(queue->links));
1025  queue->size = 0;
1026 }
SHM_QUEUE links
Definition: lock.h:32
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
int size
Definition: lock.h:33

◆ ProcReleaseLocks()

void ProcReleaseLocks ( bool  isCommit)

Definition at line 771 of file proc.c.

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

Referenced by ResourceOwnerReleaseInternal().

772 {
773  if (!MyProc)
774  return;
775  /* If waiting, get off wait queue (should only be needed after error) */
777  /* Release standard locks, including session-level if aborting */
779  /* Release transaction-level advisory locks */
781 }
PGPROC * MyProc
Definition: proc.c:67
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
#define USER_LOCKMETHOD
Definition: lock.h:129
void LockErrorCleanup(void)
Definition: proc.c:695
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2089

◆ ProcSendSignal()

void ProcSendSignal ( int  pid)

Definition at line 1796 of file proc.c.

References BackendPidGetProc(), PGPROC::procLatch, ProcStructLock, RecoveryInProgress(), SetLatch(), SpinLockAcquire, SpinLockRelease, PROC_HDR::startupProc, and PROC_HDR::startupProcPid.

Referenced by ReleasePredicateLocks(), and UnpinBuffer().

1797 {
1798  PGPROC *proc = NULL;
1799 
1800  if (RecoveryInProgress())
1801  {
1803 
1804  /*
1805  * Check to see whether it is the Startup process we wish to signal.
1806  * This call is made by the buffer manager when it wishes to wake up a
1807  * process that has been waiting for a pin in so it can obtain a
1808  * cleanup lock using LockBufferForCleanup(). Startup is not a normal
1809  * backend, so BackendPidGetProc() will not return any pid at all. So
1810  * we remember the information for this special case.
1811  */
1812  if (pid == ProcGlobal->startupProcPid)
1813  proc = ProcGlobal->startupProc;
1814 
1816  }
1817 
1818  if (proc == NULL)
1819  proc = BackendPidGetProc(pid);
1820 
1821  if (proc != NULL)
1822  {
1823  SetLatch(&proc->procLatch);
1824  }
1825 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2379
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool RecoveryInProgress(void)
Definition: xlog.c:7888
Latch procLatch
Definition: proc.h:104
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
int startupProcPid
Definition: proc.h:270
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
void SetLatch(volatile Latch *latch)
Definition: latch.c:436
PGPROC * startupProc
Definition: proc.h:269
Definition: proc.h:95

◆ ProcSleep()

int ProcSleep ( LOCALLOCK locallock,
LockMethod  lockMethodTable 
)

Definition at line 1046 of file proc.c.

References _, PROC_HDR::allPgXact, appendStringInfo(), Assert, buf, CHECK_FOR_INTERRUPTS, CheckDeadLock(), CheckRecoveryConflictDeadlock(), LockMethodData::conflictTab, 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(), get_timeout_start_time(), GetBlockingAutoVacuumPgproc(), GetCurrentTimestamp(), GetLockmodeName(), got_deadlock_timeout, GrantAwaitedLock(), GrantLock(), PROCLOCK::groupLeader, LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, i, EnableTimeoutParams::id, DisableTimeoutParams::id, InHotStandby, initStringInfo(), InRecovery, DisableTimeoutParams::keep_indicator, kill, PROC_QUEUE::links, PGPROC::links, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_TIMEOUT, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, PROCLOCK::lockLink, LOCKTAG::locktag_lockmethodid, LOCKTAG::locktag_type, LockTimeout, LOG, log_lock_waits, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), LOCALLOCKTAG::mode, MyLatch, PROCLOCKTAG::myProc, MyProcPid, SHM_QUEUE::next, offsetof, pfree(), PG_WAIT_LOCK, PGPROC::pgprocno, PGPROC::pid, PROC_IS_AUTOVACUUM, PROC_VACUUM_FOR_WRAPAROUND, LOCALLOCK::proclock, LOCK::procLocks, RecoveryInProgress(), RememberSimpleDeadLock(), RemoveFromWaitQueue(), ResetLatch(), ResolveRecoveryConflictWithLock(), SHMQueueInsertBefore(), SHMQueueNext(), PROC_QUEUE::size, STATUS_ERROR, STATUS_OK, STATUS_WAITING, LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, TimestampDifference(), TMPARAM_AFTER, EnableTimeoutParams::type, PGXACT::vacuumFlags, WaitLatch(), PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, PGPROC::waitStatus, WARNING, WL_EXIT_ON_PM_DEATH, and WL_LATCH_SET.

Referenced by WaitOnLock().

1047 {
1048  LOCKMODE lockmode = locallock->tag.mode;
1049  LOCK *lock = locallock->lock;
1050  PROCLOCK *proclock = locallock->proclock;
1051  uint32 hashcode = locallock->hashcode;
1052  LWLock *partitionLock = LockHashPartitionLock(hashcode);
1053  PROC_QUEUE *waitQueue = &(lock->waitProcs);
1054  LOCKMASK myHeldLocks = MyProc->heldLocks;
1055  bool early_deadlock = false;
1056  bool allow_autovacuum_cancel = true;
1057  int myWaitStatus;
1058  PGPROC *proc;
1059  PGPROC *leader = MyProc->lockGroupLeader;
1060  int i;
1061 
1062  /*
1063  * If group locking is in use, locks held by members of my locking group
1064  * need to be included in myHeldLocks.
1065  */
1066  if (leader != NULL)
1067  {
1068  SHM_QUEUE *procLocks = &(lock->procLocks);
1069  PROCLOCK *otherproclock;
1070 
1071  otherproclock = (PROCLOCK *)
1072  SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink));
1073  while (otherproclock != NULL)
1074  {
1075  if (otherproclock->groupLeader == leader)
1076  myHeldLocks |= otherproclock->holdMask;
1077  otherproclock = (PROCLOCK *)
1078  SHMQueueNext(procLocks, &otherproclock->lockLink,
1079  offsetof(PROCLOCK, lockLink));
1080  }
1081  }
1082 
1083  /*
1084  * Determine where to add myself in the wait queue.
1085  *
1086  * Normally I should go at the end of the queue. However, if I already
1087  * hold locks that conflict with the request of any previous waiter, put
1088  * myself in the queue just in front of the first such waiter. This is not
1089  * a necessary step, since deadlock detection would move me to before that
1090  * waiter anyway; but it's relatively cheap to detect such a conflict
1091  * immediately, and avoid delaying till deadlock timeout.
1092  *
1093  * Special case: if I find I should go in front of some waiter, check to
1094  * see if I conflict with already-held locks or the requests before that
1095  * waiter. If not, then just grant myself the requested lock immediately.
1096  * This is the same as the test for immediate grant in LockAcquire, except
1097  * we are only considering the part of the wait queue before my insertion
1098  * point.
1099  */
1100  if (myHeldLocks != 0)
1101  {
1102  LOCKMASK aheadRequests = 0;
1103 
1104  proc = (PGPROC *) waitQueue->links.next;
1105  for (i = 0; i < waitQueue->size; i++)
1106  {
1107  /*
1108  * If we're part of the same locking group as this waiter, its
1109  * locks neither conflict with ours nor contribute to
1110  * aheadRequests.
1111  */
1112  if (leader != NULL && leader == proc->lockGroupLeader)
1113  {
1114  proc = (PGPROC *) proc->links.next;
1115  continue;
1116  }
1117  /* Must he wait for me? */
1118  if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
1119  {
1120  /* Must I wait for him ? */
1121  if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
1122  {
1123  /*
1124  * Yes, so we have a deadlock. Easiest way to clean up
1125  * correctly is to call RemoveFromWaitQueue(), but we
1126  * can't do that until we are *on* the wait queue. So, set
1127  * a flag to check below, and break out of loop. Also,
1128  * record deadlock info for later message.
1129  */
1130  RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
1131  early_deadlock = true;
1132  break;
1133  }
1134  /* I must go before this waiter. Check special case. */
1135  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1136  LockCheckConflicts(lockMethodTable,
1137  lockmode,
1138  lock,
1139  proclock) == STATUS_OK)
1140  {
1141  /* Skip the wait and just grant myself the lock. */
1142  GrantLock(lock, proclock, lockmode);
1143  GrantAwaitedLock();
1144  return STATUS_OK;
1145  }
1146  /* Break out of loop to put myself before him */
1147  break;
1148  }
1149  /* Nope, so advance to next waiter */
1150  aheadRequests |= LOCKBIT_ON(proc->waitLockMode);
1151  proc = (PGPROC *) proc->links.next;
1152  }
1153 
1154  /*
1155  * If we fall out of loop normally, proc points to waitQueue head, so
1156  * we will insert at tail of queue as desired.
1157  */
1158  }
1159  else
1160  {
1161  /* I hold no locks, so I can't push in front of anyone. */
1162  proc = (PGPROC *) &(waitQueue->links);
1163  }
1164 
1165  /*
1166  * Insert self into queue, ahead of the given proc (or at tail of queue).
1167  */
1168  SHMQueueInsertBefore(&(proc->links), &(MyProc->links));
1169  waitQueue->size++;
1170 
1171  lock->waitMask |= LOCKBIT_ON(lockmode);
1172 
1173  /* Set up wait information in PGPROC object, too */
1174  MyProc->waitLock = lock;
1175  MyProc->waitProcLock = proclock;
1176  MyProc->waitLockMode = lockmode;
1177 
1179 
1180  /*
1181  * If we detected deadlock, give up without waiting. This must agree with
1182  * CheckDeadLock's recovery code, except that we shouldn't release the
1183  * semaphore since we haven't tried to lock it yet.
1184  */
1185  if (early_deadlock)
1186  {
1187  RemoveFromWaitQueue(MyProc, hashcode);
1188  return STATUS_ERROR;
1189  }
1190 
1191  /* mark that we are waiting for a lock */
1192  lockAwaited = locallock;
1193 
1194  /*
1195  * Release the lock table's partition lock.
1196  *
1197  * NOTE: this may also cause us to exit critical-section state, possibly
1198  * allowing a cancel/die interrupt to be accepted. This is OK because we
1199  * have recorded the fact that we are waiting for a lock, and so
1200  * LockErrorCleanup will clean up if cancel/die happens.
1201  */
1202  LWLockRelease(partitionLock);
1203 
1204  /*
1205  * Also, now that we will successfully clean up after an ereport, it's
1206  * safe to check to see if there's a buffer pin deadlock against the
1207  * Startup process. Of course, that's only necessary if we're doing Hot
1208  * Standby and are not the Startup process ourselves.
1209  */
1210  if (RecoveryInProgress() && !InRecovery)
1212 
1213  /* Reset deadlock_state before enabling the timeout handler */
1215  got_deadlock_timeout = false;
1216 
1217  /*
1218  * Set timer so we can wake up after awhile and check for a deadlock. If a
1219  * deadlock is detected, the handler releases the process's semaphore and
1220  * sets MyProc->waitStatus = STATUS_ERROR, allowing us to know that we
1221  * must report failure rather than success.
1222  *
1223  * By delaying the check until we've waited for a bit, we can avoid
1224  * running the rather expensive deadlock-check code in most cases.
1225  *
1226  * If LockTimeout is set, also enable the timeout for that. We can save a
1227  * few cycles by enabling both timeout sources in one call.
1228  *
1229  * If InHotStandby we set lock waits slightly later for clarity with other
1230  * code.
1231  */
1232  if (!InHotStandby)
1233  {
1234  if (LockTimeout > 0)
1235  {
1236  EnableTimeoutParams timeouts[2];
1237 
1238  timeouts[0].id = DEADLOCK_TIMEOUT;
1239  timeouts[0].type = TMPARAM_AFTER;
1240  timeouts[0].delay_ms = DeadlockTimeout;
1241  timeouts[1].id = LOCK_TIMEOUT;
1242  timeouts[1].type = TMPARAM_AFTER;
1243  timeouts[1].delay_ms = LockTimeout;
1244  enable_timeouts(timeouts, 2);
1245  }
1246  else
1248  }
1249 
1250  /*
1251  * If somebody wakes us between LWLockRelease and WaitLatch, the latch
1252  * will not wait. But a set latch does not necessarily mean that the lock
1253  * is free now, as there are many other sources for latch sets than
1254  * somebody releasing the lock.
1255  *
1256  * We process interrupts whenever the latch has been set, so cancel/die
1257  * interrupts are processed quickly. This means we must not mind losing
1258  * control to a cancel/die interrupt here. We don't, because we have no
1259  * shared-state-change work to do after being granted the lock (the
1260  * grantor did it all). We do have to worry about canceling the deadlock
1261  * timeout and updating the locallock table, but if we lose control to an
1262  * error, LockErrorCleanup will fix that up.
1263  */
1264  do
1265  {
1266  if (InHotStandby)
1267  {
1268  /* Set a timer and wait for that or for the Lock to be granted */
1270  }
1271  else
1272  {
1274  PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
1276  /* check for deadlocks first, as that's probably log-worthy */
1278  {
1279  CheckDeadLock();
1280  got_deadlock_timeout = false;
1281  }
1283  }
1284 
1285  /*
1286  * waitStatus could change from STATUS_WAITING to something else
1287  * asynchronously. Read it just once per loop to prevent surprising
1288  * behavior (such as missing log messages).
1289  */
1290  myWaitStatus = *((volatile int *) &MyProc->waitStatus);
1291 
1292  /*
1293  * If we are not deadlocked, but are waiting on an autovacuum-induced
1294  * task, send a signal to interrupt it.
1295  */
1296  if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
1297  {
1298  PGPROC *autovac = GetBlockingAutoVacuumPgproc();
1299  PGXACT *autovac_pgxact = &ProcGlobal->allPgXact[autovac->pgprocno];
1300 
1301  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1302 
1303  /*
1304  * Only do it if the worker is not working to protect against Xid
1305  * wraparound.
1306  */
1307  if ((autovac_pgxact->vacuumFlags & PROC_IS_AUTOVACUUM) &&
1308  !(autovac_pgxact->vacuumFlags & PROC_VACUUM_FOR_WRAPAROUND))
1309  {
1310  int pid = autovac->pid;
1311  StringInfoData locktagbuf;
1312  StringInfoData logbuf; /* errdetail for server log */
1313 
1314  initStringInfo(&locktagbuf);
1315  initStringInfo(&logbuf);
1316  DescribeLockTag(&locktagbuf, &lock->tag);
1317  appendStringInfo(&logbuf,
1318  _("Process %d waits for %s on %s."),
1319  MyProcPid,
1321  lockmode),
1322  locktagbuf.data);
1323 
1324  /* release lock as quickly as possible */
1325  LWLockRelease(ProcArrayLock);
1326 
1327  /* send the autovacuum worker Back to Old Kent Road */
1328  ereport(DEBUG1,
1329  (errmsg("sending cancel to blocking autovacuum PID %d",
1330  pid),
1331  errdetail_log("%s", logbuf.data)));
1332 
1333  if (kill(pid, SIGINT) < 0)
1334  {
1335  /*
1336  * There's a race condition here: once we release the
1337  * ProcArrayLock, it's possible for the autovac worker to
1338  * close up shop and exit before we can do the kill().
1339  * Therefore, we do not whinge about no-such-process.
1340  * Other errors such as EPERM could conceivably happen if
1341  * the kernel recycles the PID fast enough, but such cases
1342  * seem improbable enough that it's probably best to issue
1343  * a warning if we see some other errno.
1344  */
1345  if (errno != ESRCH)
1346  ereport(WARNING,
1347  (errmsg("could not send signal to process %d: %m",
1348  pid)));
1349  }
1350 
1351  pfree(logbuf.data);
1352  pfree(locktagbuf.data);
1353  }
1354  else
1355  LWLockRelease(ProcArrayLock);
1356 
1357  /* prevent signal from being resent more than once */
1358  allow_autovacuum_cancel = false;
1359  }
1360 
1361  /*
1362  * If awoken after the deadlock check interrupt has run, and
1363  * log_lock_waits is on, then report about the wait.
1364  */
1366  {
1368  lock_waiters_sbuf,
1369  lock_holders_sbuf;
1370  const char *modename;
1371  long secs;
1372  int usecs;
1373  long msecs;
1374  SHM_QUEUE *procLocks;
1375  PROCLOCK *proclock;
1376  bool first_holder = true,
1377  first_waiter = true;
1378  int lockHoldersNum = 0;
1379 
1380  initStringInfo(&buf);
1381  initStringInfo(&lock_waiters_sbuf);
1382  initStringInfo(&lock_holders_sbuf);
1383 
1384  DescribeLockTag(&buf, &locallock->tag.lock);
1385  modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1386  lockmode);
1389  &secs, &usecs);
1390  msecs = secs * 1000 + usecs / 1000;
1391  usecs = usecs % 1000;
1392 
1393  /*
1394  * we loop over the lock's procLocks to gather a list of all
1395  * holders and waiters. Thus we will be able to provide more
1396  * detailed information for lock debugging purposes.
1397  *
1398  * lock->procLocks contains all processes which hold or wait for
1399  * this lock.
1400  */
1401 
1402  LWLockAcquire(partitionLock, LW_SHARED);
1403 
1404  procLocks = &(lock->procLocks);
1405  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
1406  offsetof(PROCLOCK, lockLink));
1407 
1408  while (proclock)
1409  {
1410  /*
1411  * we are a waiter if myProc->waitProcLock == proclock; we are
1412  * a holder if it is NULL or something different
1413  */
1414  if (proclock->tag.myProc->waitProcLock == proclock)
1415  {
1416  if (first_waiter)
1417  {
1418  appendStringInfo(&lock_waiters_sbuf, "%d",
1419  proclock->tag.myProc->pid);
1420  first_waiter = false;
1421  }
1422  else
1423  appendStringInfo(&lock_waiters_sbuf, ", %d",
1424  proclock->tag.myProc->pid);
1425  }
1426  else
1427  {
1428  if (first_holder)
1429  {
1430  appendStringInfo(&lock_holders_sbuf, "%d",
1431  proclock->tag.myProc->pid);
1432  first_holder = false;
1433  }
1434  else
1435  appendStringInfo(&lock_holders_sbuf, ", %d",
1436  proclock->tag.myProc->pid);
1437 
1438  lockHoldersNum++;
1439  }
1440 
1441  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
1442  offsetof(PROCLOCK, lockLink));
1443  }
1444 
1445  LWLockRelease(partitionLock);
1446 
1448  ereport(LOG,
1449  (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
1450  MyProcPid, modename, buf.data, msecs, usecs),
1451  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1452  "Processes holding the lock: %s. Wait queue: %s.",
1453  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1454  else if (deadlock_state == DS_HARD_DEADLOCK)
1455  {
1456  /*
1457  * This message is a bit redundant with the error that will be
1458  * reported subsequently, but in some cases the error report
1459  * might not make it to the log (eg, if it's caught by an
1460  * exception handler), and we want to ensure all long-wait
1461  * events get logged.
1462  */
1463  ereport(LOG,
1464  (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
1465  MyProcPid, modename, buf.data, msecs, usecs),
1466  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1467  "Processes holding the lock: %s. Wait queue: %s.",
1468  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1469  }
1470 
1471  if (myWaitStatus == STATUS_WAITING)
1472  ereport(LOG,
1473  (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
1474  MyProcPid, modename, buf.data, msecs, usecs),
1475  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1476  "Processes holding the lock: %s. Wait queue: %s.",
1477  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1478  else if (myWaitStatus == STATUS_OK)
1479  ereport(LOG,
1480  (errmsg("process %d acquired %s on %s after %ld.%03d ms",
1481  MyProcPid, modename, buf.data, msecs, usecs)));
1482  else
1483  {
1484  Assert(myWaitStatus == STATUS_ERROR);
1485 
1486  /*
1487  * Currently, the deadlock checker always kicks its own
1488  * process, which means that we'll only see STATUS_ERROR when
1489  * deadlock_state == DS_HARD_DEADLOCK, and there's no need to
1490  * print redundant messages. But for completeness and
1491  * future-proofing, print a message if it looks like someone
1492  * else kicked us off the lock.
1493  */
1495  ereport(LOG,
1496  (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
1497  MyProcPid, modename, buf.data, msecs, usecs),
1498  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
1499  "Processes holding the lock: %s. Wait queue: %s.",
1500  lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
1501  }
1502 
1503  /*
1504  * At this point we might still need to wait for the lock. Reset
1505  * state so we don't print the above messages again.
1506  */
1508 
1509  pfree(buf.data);
1510  pfree(lock_holders_sbuf.data);
1511  pfree(lock_waiters_sbuf.data);
1512  }
1513  } while (myWaitStatus == STATUS_WAITING);
1514 
1515  /*
1516  * Disable the timers, if they are still running. As in LockErrorCleanup,
1517  * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
1518  * already caused QueryCancelPending to become set, we want the cancel to
1519  * be reported as a lock timeout, not a user cancel.
1520  */
1521  if (!InHotStandby)
1522  {
1523  if (LockTimeout > 0)
1524  {
1525  DisableTimeoutParams timeouts[2];
1526 
1527  timeouts[0].id = DEADLOCK_TIMEOUT;
1528  timeouts[0].keep_indicator = false;
1529  timeouts[1].id = LOCK_TIMEOUT;
1530  timeouts[1].keep_indicator = true;
1531  disable_timeouts(timeouts, 2);
1532  }
1533  else
1535  }
1536 
1537  /*
1538  * Re-acquire the lock table's partition lock. We have to do this to hold
1539  * off cancel/die interrupts before we can mess with lockAwaited (else we
1540  * might have a missed or duplicated locallock update).
1541  */
1542  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
1543 
1544  /*
1545  * We no longer want LockErrorCleanup to do anything.
1546  */
1547  lockAwaited = NULL;
1548 
1549  /*
1550  * If we got the lock, be sure to remember it in the locallock table.
1551  */
1552  if (MyProc->waitStatus == STATUS_OK)
1553  GrantAwaitedLock();
1554 
1555  /*
1556  * We don't have to do anything else, because the awaker did all the
1557  * necessary update of the lock table and MyProc.
1558  */
1559  return MyProc->waitStatus;
1560 }
TimestampTz get_timeout_start_time(TimeoutId id)
Definition: timeout.c:653
PROCLOCKTAG tag
Definition: lock.h:347
void ResolveRecoveryConflictWithLock(LOCKTAG locktag)
Definition: standby.c:389
uint32 hashcode
Definition: lock.h:409
#define PG_WAIT_LOCK
Definition: pgstat.h:738
Definition: lwlock.h:32
TimeoutId id
Definition: timeout.h:54
int LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1344
LOCALLOCKTAG tag
Definition: lock.h:404
#define DEBUG1
Definition: elog.h:25
int MyProcPid
Definition: globals.c:40
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:3920
LOCKTAG lock
Definition: lock.h:385
void GrantAwaitedLock(void)
Definition: lock.c:1695
Definition: proc.h:222
int LOCKMODE
Definition: lockdefs.h:26
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
SHM_QUEUE links
Definition: lock.h:32
PGXACT * allPgXact
Definition: proc.h:249
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1467
SHM_QUEUE links
Definition: proc.h:98
TimeoutType type
Definition: timeout.h:55
struct SHM_QUEUE * next
Definition: shmem.h:31
LOCKMODE waitLockMode
Definition: proc.h:141
bool InRecovery
Definition: xlog.c:197
LOCKTAG tag
Definition: lock.h:287
#define PROC_VACUUM_FOR_WRAPAROUND
Definition: proc.h:56
const LOCKMASK * conflictTab
Definition: lock.h:114
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
SHM_QUEUE lockLink
Definition: lock.h:353
#define InHotStandby
Definition: xlog.h:74
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define STATUS_ERROR
Definition: c.h:1076
#define kill(pid, sig)
Definition: win32_port.h:435
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
void ResetLatch(volatile Latch *latch)
Definition: latch.c:519
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:7888
void disable_timeouts(const DisableTimeoutParams *timeouts, int count)
Definition: timeout.c:561
PROC_QUEUE waitProcs
Definition: lock.h:293
uint8 vacuumFlags
Definition: proc.h:233
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition: deadlock.c:1149
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:344
void enable_timeouts(const EnableTimeoutParams *timeouts, int count)
Definition: timeout.c:476
void pfree(void *pointer)
Definition: mcxt.c:1031
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
static DeadLockState deadlock_state
Definition: proc.c:87
TimeoutId id
Definition: timeout.h:65
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1047
PROCLOCK * waitProcLock
Definition: proc.h:140
static char * buf
Definition: pg_test_fsync.c:67
static volatile sig_atomic_t got_deadlock_timeout
Definition: proc.c:90
unsigned int uint32
Definition: c.h:358
int errdetail_log(const char *fmt,...)
Definition: elog.c:908
void CheckRecoveryConflictDeadlock(void)
Definition: standby.c:542
Definition: lock.h:284
LOCK * waitLock
Definition: proc.h:139
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1075
LOCKMASK waitMask
Definition: lock.h:291
SHM_QUEUE procLocks
Definition: lock.h:292
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define WARNING
Definition: elog.h:40
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1827
int waitStatus
Definition: proc.h:102
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:929
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:428
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:732
bool log_lock_waits
Definition: proc.c:64
static LOCALLOCK * lockAwaited
Definition: proc.c:85
int LockTimeout
Definition: proc.c:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
LOCK * lock
Definition: lock.h:407
int LOCKMASK
Definition: lockdefs.h:25
static void CheckDeadLock(void)
Definition: proc.c:1674
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
int pgprocno
Definition: proc.h:110
int errmsg(const char *fmt,...)
Definition: elog.c:784
int i
int size
Definition: lock.h:33
struct Latch * MyLatch
Definition: globals.c:54
int DeadlockTimeout
Definition: proc.c:60
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define STATUS_WAITING
Definition: c.h:1079
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition: deadlock.c:293
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:525
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1644
Definition: proc.h:95
int pid
Definition: proc.h:109
#define WL_LATCH_SET
Definition: latch.h:124
#define _(x)
Definition: elog.c:84
PGPROC * lockGroupLeader
Definition: proc.h:203
#define PROC_IS_AUTOVACUUM
Definition: proc.h:53
#define offsetof(type, field)
Definition: c.h:655
LOCKMASK heldLocks
Definition: proc.h:142
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:129
PGPROC * groupLeader
Definition: lock.h:350

◆ ProcWaitForSignal()

void ProcWaitForSignal ( uint32  wait_event_info)

Definition at line 1784 of file proc.c.

References CHECK_FOR_INTERRUPTS, MyLatch, ResetLatch(), WaitLatch(), WL_EXIT_ON_PM_DEATH, and WL_LATCH_SET.

Referenced by GetSafeSnapshot(), LockBufferForCleanup(), ResolveRecoveryConflictWithBufferPin(), and ResolveRecoveryConflictWithLock().

1785 {
1787  wait_event_info);
1790 }
void ResetLatch(volatile Latch *latch)
Definition: latch.c:519
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:344
struct Latch * MyLatch
Definition: globals.c:54
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define WL_LATCH_SET
Definition: latch.h:124
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:129

◆ ProcWakeup()

PGPROC* ProcWakeup ( PGPROC proc,
int  waitStatus 
)

Definition at line 1577 of file proc.c.

References Assert, PGPROC::links, SHM_QUEUE::next, SHM_QUEUE::prev, PGPROC::procLatch, SetLatch(), SHMQueueDelete(), PROC_QUEUE::size, STATUS_WAITING, PGPROC::waitLock, PGPROC::waitProcLock, LOCK::waitProcs, and PGPROC::waitStatus.

Referenced by ProcLockWakeup().

1578 {
1579  PGPROC *retProc;
1580 
1581  /* Proc should be sleeping ... */
1582  if (proc->links.prev == NULL ||
1583  proc->links.next == NULL)
1584  return NULL;
1585  Assert(proc->waitStatus == STATUS_WAITING);
1586 
1587  /* Save next process before we zap the list link */
1588  retProc = (PGPROC *) proc->links.next;
1589 
1590  /* Remove process from wait queue */
1591  SHMQueueDelete(&(proc->links));
1592  (proc->waitLock->waitProcs.size)--;
1593 
1594  /* Clean up process' state and pass it the ok/fail signal */
1595  proc->waitLock = NULL;
1596  proc->waitProcLock = NULL;
1597  proc->waitStatus = waitStatus;
1598 
1599  /* And awaken it */
1600  SetLatch(&proc->procLatch);
1601 
1602  return retProc;
1603 }
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
Latch procLatch
Definition: proc.h:104
PROC_QUEUE waitProcs
Definition: lock.h:293
PROCLOCK * waitProcLock
Definition: proc.h:140
LOCK * waitLock
Definition: proc.h:139
int waitStatus
Definition: proc.h:102
void SetLatch(volatile Latch *latch)
Definition: latch.c:436
struct SHM_QUEUE * prev
Definition: shmem.h:30
#define Assert(condition)
Definition: c.h:732
int size
Definition: lock.h:33
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define STATUS_WAITING
Definition: c.h:1079
Definition: proc.h:95

◆ PublishStartupProcessInformation()

void PublishStartupProcessInformation ( void  )

Definition at line 611 of file proc.c.

References MyProc, MyProcPid, ProcStructLock, SpinLockAcquire, SpinLockRelease, PROC_HDR::startupProc, and PROC_HDR::startupProcPid.

Referenced by StartupXLOG().

612 {
614 
617 
619 }
int MyProcPid
Definition: globals.c:40
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
int startupProcPid
Definition: proc.h:270
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
PGPROC * startupProc
Definition: proc.h:269

◆ RemoveProcFromArray()

static void RemoveProcFromArray ( int  code,
Datum  arg 
)
static

Definition at line 788 of file proc.c.

References Assert, InvalidTransactionId, and ProcArrayRemove().

Referenced by InitProcessPhase2().

789 {
790  Assert(MyProc != NULL);
792 }
PGPROC * MyProc
Definition: proc.c:67
void ProcArrayRemove(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:334
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:732

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 629 of file proc.c.

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

630 {
631  /* use volatile pointer to prevent code rearrangement */
632  volatile PROC_HDR *procglobal = ProcGlobal;
633 
634  procglobal->startupBufferPinWaitBufId = bufid;
635 }
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: proc.h:244
int startupBufferPinWaitBufId
Definition: proc.h:272

Variable Documentation

◆ AuxiliaryProcs

◆ deadlock_state

DeadLockState deadlock_state = DS_NOT_YET_CHECKED
static

Definition at line 87 of file proc.c.

Referenced by CheckDeadLock(), and ProcSleep().

◆ DeadlockTimeout

int DeadlockTimeout = 1000

Definition at line 60 of file proc.c.

Referenced by ProcSleep(), and ResolveRecoveryConflictWithBufferPin().

◆ got_deadlock_timeout

volatile sig_atomic_t got_deadlock_timeout
static

Definition at line 90 of file proc.c.

Referenced by CheckDeadLockAlert(), and ProcSleep().

◆ IdleInTransactionSessionTimeout

int IdleInTransactionSessionTimeout = 0

Definition at line 63 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ lockAwaited

LOCALLOCK* lockAwaited = NULL
static

Definition at line 85 of file proc.c.

◆ LockTimeout

int LockTimeout = 0

Definition at line 62 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

bool log_lock_waits = false

Definition at line 64 of file proc.c.

Referenced by ProcSleep().

◆ MyPgXact

◆ MyProc

PGPROC* MyProc = NULL

Definition at line 67 of file proc.c.

Referenced by AbortTransaction(), apw_sighup_handler(), apw_sigterm_handler(), AtEOSubXact_Namespace(), AtEOXact_Namespace(), attach_to_queues(), autoprewarm_main(), AutoVacWorkerMain(), AuxiliaryProcKill(), BackgroundWriterMain(), BecomeLockGroupLeader(), CheckpointerMain(), CommitTransaction(), ConditionVariableBroadcast(), ConditionVariableCancelSleep(), ConditionVariablePrepareToSleep(), ConditionVariableSleep(), CountOtherDBBackends(), CreateReplicationSlot(), errdetail_abort(), exec_eval_simple_expr(), exec_stmt_call(), ExecParallelGetReceiver(), ExecParallelSetupTupleQueues(), ExportSnapshot(), FastPathGetRelationLockEntry(), FastPathGrantRelationLock(), FastPathUnGrantRelationLock(), FindLockCycleRecurseMember(), fmgr_sql(), get_cast_hashentry(), GetCurrentVirtualXIDs(), GetLockConflicts(), GetLockmodeName(), GetNewTransactionId(), GetSerializableTransactionSnapshotInt(), GetStableLatestTransactionId(), init_sql_fcache(), InitializeParallelDSM(), InitializeSessionUserId(), InitPostgres(), InitTempTableNamespace(), InitWalSenderSlot(), lock_and_open_sequence(), LockAcquireExtended(), LockCheckConflicts(), LockRelease(), LockReleaseAll(), log_line_prefix(), logicalrep_worker_attach(), LWLockAcquire(), LWLockAcquireOrWait(), LWLockAttemptLock(), LWLockDequeueSelf(), LWLockQueueSelf(), LWLockWaitForVar(), MinimumActiveBackends(), ParallelWorkerMain(), pgstat_report_activity(), pgstat_report_wait_end(), pgstat_report_wait_start(), PostPrepare_Locks(), PrepareTransaction(), ProcArrayGroupClearXid(), ProcKill(), PublishStartupProcessInformation(), RecoveryConflictInterrupt(), ReinitializeParallelDSM(), setup_dynamic_shared_memory(), SharedInvalBackendInit(), shm_mq_attach(), shm_mq_detach_internal(), shm_mq_receive(), shm_mq_sendv(), shm_mq_wait_for_attach(), StartTransaction(), SwitchBackToLocalLatch(), SwitchToSharedLatch(), SyncRepCancelWait(), SyncRepCleanupAtProcExit(), SyncRepQueueInsert(), SyncRepWaitForLSN(), TransactionGroupUpdateXidStatus(), TransactionIdIsInProgress(), TransactionIdSetPageStatus(), VirtualXactLockTableCleanup(), VirtualXactLockTableInsert(), WaitXLogInsertionsToFinish(), WALInsertLockAcquire(), WalReceiverMain(), WalWriterMain(), write_csvlog(), and XidCacheRemoveRunningXids().

◆ PreparedXactProcs

PGPROC* PreparedXactProcs = NULL

Definition at line 82 of file proc.c.

Referenced by PostmasterMarkPIDForWorkerNotify(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ ProcStructLock

◆ StatementTimeout

int StatementTimeout = 0

Definition at line 61 of file proc.c.

Referenced by enable_statement_timeout().