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

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

Referenced by pg_stat_get_activity().

963 {
964  PGPROC *result = NULL;
965  int index;
966 
967  if (pid == 0) /* never match dummy PGPROCs */
968  return NULL;
969 
970  for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
971  {
972  PGPROC *proc = &AuxiliaryProcs[index];
973 
974  if (proc->pid == pid)
975  {
976  result = proc;
977  break;
978  }
979  }
980  return result;
981 }
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 915 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().

916 {
917  int proctype = DatumGetInt32(arg);
919  PGPROC *proc;
920 
921  Assert(proctype >= 0 && proctype < NUM_AUXILIARY_PROCS);
922 
923  auxproc = &AuxiliaryProcs[proctype];
924 
925  Assert(MyProc == auxproc);
926 
927  /* Release any LW locks I am holding (see notes above) */
929 
930  /* Cancel any pending condition variable sleep, too */
932 
933  /*
934  * Reset MyLatch to the process local one. This is so that signal
935  * handlers et al can continue using the latch after the shared latch
936  * isn't ours anymore. After that clear MyProc and disown the shared
937  * latch.
938  */
940  proc = MyProc;
941  MyProc = NULL;
942  DisownLatch(&proc->procLatch);
943 
945 
946  /* Mark auxiliary proc no longer in use */
947  proc->pid = 0;
948 
949  /* Update shared estimate of spins_per_delay */
951 
953 }
#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:373
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:308
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 1826 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().

1827 {
1828  LWLock *leader_lwlock;
1829 
1830  /* If we already did it, we don't need to do it again. */
1831  if (MyProc->lockGroupLeader == MyProc)
1832  return;
1833 
1834  /* We had better not be a follower. */
1835  Assert(MyProc->lockGroupLeader == NULL);
1836 
1837  /* Create single-member group, containing only ourselves. */
1838  leader_lwlock = LockHashPartitionLockByProc(MyProc);
1839  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1842  LWLockRelease(leader_lwlock);
1843 }
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 1856 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().

1857 {
1858  LWLock *leader_lwlock;
1859  bool ok = false;
1860 
1861  /* Group leader can't become member of group */
1862  Assert(MyProc != leader);
1863 
1864  /* Can't already be a member of a group */
1865  Assert(MyProc->lockGroupLeader == NULL);
1866 
1867  /* PID must be valid. */
1868  Assert(pid != 0);
1869 
1870  /*
1871  * Get lock protecting the group fields. Note LockHashPartitionLockByProc
1872  * accesses leader->pgprocno in a PGPROC that might be free. This is safe
1873  * because all PGPROCs' pgprocno fields are set during shared memory
1874  * initialization and never change thereafter; so we will acquire the
1875  * correct lock even if the leader PGPROC is in process of being recycled.
1876  */
1877  leader_lwlock = LockHashPartitionLockByProc(leader);
1878  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1879 
1880  /* Is this the leader we're looking for? */
1881  if (leader->pid == pid && leader->lockGroupLeader == leader)
1882  {
1883  /* OK, join the group */
1884  ok = true;
1885  MyProc->lockGroupLeader = leader;
1887  }
1888  LWLockRelease(leader_lwlock);
1889 
1890  return ok;
1891 }
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 1667 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().

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

References got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres().

1755 {
1756  int save_errno = errno;
1757 
1758  got_deadlock_timeout = true;
1759 
1760  /*
1761  * Have to set the latch again, even if handle_sig_alarm already did. Back
1762  * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1763  * ever would be a problem, but setting a set latch again is cheap.
1764  */
1765  SetLatch(MyLatch);
1766  errno = save_errno;
1767 }
static volatile sig_atomic_t got_deadlock_timeout
Definition: proc.c:90
void SetLatch(volatile Latch *latch)
Definition: latch.c:414
struct Latch * MyLatch
Definition: globals.c:53

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 634 of file proc.c.

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery().

635 {
636  /* use volatile pointer to prevent code rearrangement */
637  volatile PROC_HDR *procglobal = ProcGlobal;
638 
639  return procglobal->startupBufferPinWaitBufId;
640 }
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 648 of file proc.c.

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

Referenced by InitPostgres().

649 {
650  PGPROC *proc;
651 
653 
654  proc = ProcGlobal->freeProcs;
655 
656  while (n > 0 && proc != NULL)
657  {
658  proc = (PGPROC *) proc->links.next;
659  n--;
660  }
661 
663 
664  return (n <= 0);
665 }
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 492 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().

493 {
494  PGPROC *auxproc;
495  int proctype;
496 
497  /*
498  * ProcGlobal should be set up already (if we are a backend, we inherit
499  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
500  */
501  if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
502  elog(PANIC, "proc header uninitialized");
503 
504  if (MyProc != NULL)
505  elog(ERROR, "you already exist");
506 
507  /*
508  * We use the ProcStructLock to protect assignment and releasing of
509  * AuxiliaryProcs entries.
510  *
511  * While we are holding the ProcStructLock, also copy the current shared
512  * estimate of spins_per_delay to local storage.
513  */
515 
517 
518  /*
519  * Find a free auxproc ... *big* trouble if there isn't one ...
520  */
521  for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
522  {
523  auxproc = &AuxiliaryProcs[proctype];
524  if (auxproc->pid == 0)
525  break;
526  }
527  if (proctype >= NUM_AUXILIARY_PROCS)
528  {
530  elog(FATAL, "all AuxiliaryProcs are in use");
531  }
532 
533  /* Mark auxiliary proc as in use by me */
534  /* use volatile pointer to prevent code rearrangement */
535  ((volatile PGPROC *) auxproc)->pid = MyProcPid;
536 
537  MyProc = auxproc;
538  MyPgXact = &ProcGlobal->allPgXact[auxproc->pgprocno];
539 
541 
542  /*
543  * Initialize all fields of MyProc, except for those previously
544  * initialized by InitProcGlobal.
545  */
549  MyProc->fpVXIDLock = false;
558  MyPgXact->delayChkpt = false;
559  MyPgXact->vacuumFlags = 0;
560  MyProc->lwWaiting = false;
561  MyProc->lwWaitMode = 0;
562  MyProc->waitLock = NULL;
563  MyProc->waitProcLock = NULL;
564 #ifdef USE_ASSERT_CHECKING
565  {
566  int i;
567 
568  /* Last process should have released all locks. */
569  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
571  }
572 #endif
573 
574  /*
575  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
576  * on it. That allows us to repoint the process latch, which so far
577  * points to process local one, to the shared one.
578  */
581 
582  /* Check that group locking fields are in a proper initial state. */
583  Assert(MyProc->lockGroupLeader == NULL);
585 
586  /*
587  * We might be reusing a semaphore that belonged to a failed process. So
588  * be careful and reinitialize its value here. (This is not strictly
589  * necessary anymore, but seems like a good idea for cleanliness.)
590  */
592 
593  /*
594  * Arrange to clean up at process exit.
595  */
597 }
static void AuxiliaryProcKill(int code, Datum arg)
Definition: proc.c:915
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:110
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:288
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:354
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 288 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_init_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().

289 {
290  PGPROC *volatile *procgloballist;
291 
292  /*
293  * ProcGlobal should be set up already (if we are a backend, we inherit
294  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
295  */
296  if (ProcGlobal == NULL)
297  elog(PANIC, "proc header uninitialized");
298 
299  if (MyProc != NULL)
300  elog(ERROR, "you already exist");
301 
302  /* Decide which list should supply our PGPROC. */
304  procgloballist = &ProcGlobal->autovacFreeProcs;
305  else if (IsBackgroundWorker)
306  procgloballist = &ProcGlobal->bgworkerFreeProcs;
307  else
308  procgloballist = &ProcGlobal->freeProcs;
309 
310  /*
311  * Try to get a proc struct from the appropriate free list. If this
312  * fails, we must be out of PGPROC structures (not to mention semaphores).
313  *
314  * While we are holding the ProcStructLock, also copy the current shared
315  * estimate of spins_per_delay to local storage.
316  */
318 
320 
321  MyProc = *procgloballist;
322 
323  if (MyProc != NULL)
324  {
325  *procgloballist = (PGPROC *) MyProc->links.next;
327  }
328  else
329  {
330  /*
331  * If we reach here, all the PGPROCs are in use. This is one of the
332  * possible places to detect "too many backends", so give the standard
333  * error message. XXX do we need to give a different failure message
334  * in the autovacuum case?
335  */
337  ereport(FATAL,
338  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
339  errmsg("sorry, too many clients already")));
340  }
342 
343  /*
344  * Cross-check that the PGPROC is of the type we expect; if this were not
345  * the case, it would get returned to the wrong list.
346  */
347  Assert(MyProc->procgloballist == procgloballist);
348 
349  /*
350  * Now that we have a PGPROC, mark ourselves as an active postmaster
351  * child; this is so that the postmaster can detect it if we exit without
352  * cleaning up. (XXX autovac launcher currently doesn't participate in
353  * this; it probably should.)
354  */
357 
358  /*
359  * Initialize all fields of MyProc, except for those previously
360  * initialized by InitProcGlobal.
361  */
365  MyProc->fpVXIDLock = false;
369  MyProc->pid = MyProcPid;
370  /* backendId, databaseId and roleId will be filled in later */
376  MyPgXact->delayChkpt = false;
377  MyPgXact->vacuumFlags = 0;
378  /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
381  MyProc->lwWaiting = false;
382  MyProc->lwWaitMode = 0;
383  MyProc->waitLock = NULL;
384  MyProc->waitProcLock = NULL;
385 #ifdef USE_ASSERT_CHECKING
386  {
387  int i;
388 
389  /* Last process should have released all locks. */
390  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
392  }
393 #endif
395 
396  /* Initialize fields for sync rep */
397  MyProc->waitLSN = 0;
400 
401  /* Initialize fields for group XID clearing. */
402  MyProc->procArrayGroupMember = false;
405 
406  /* Check that group locking fields are in a proper initial state. */
407  Assert(MyProc->lockGroupLeader == NULL);
409 
410  /* Initialize wait event information. */
411  MyProc->wait_event_info = 0;
412 
413  /* Initialize fields for group transaction status update. */
414  MyProc->clogGroupMember = false;
420 
421  /*
422  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
423  * on it. That allows us to repoint the process latch, which so far
424  * points to process local one, to the shared one.
425  */
428 
429  /*
430  * We might be reusing a semaphore that belonged to a failed process. So
431  * be careful and reinitialize its value here. (This is not strictly
432  * necessary anymore, but seems like a good idea for cleanliness.)
433  */
435 
436  /*
437  * Arrange to clean up at backend exit.
438  */
440 
441  /*
442  * Now that we have a PGPROC, we could try to acquire locks, so initialize
443  * local state needed for LWLocks, and the deadlock checker.
444  */
447 }
bool procArrayGroupMember
Definition: proc.h:166
static void ProcKill(int code, Datum arg)
Definition: proc.c:792
#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:572
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:110
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:108
#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:288
LOCK * waitLock
Definition: proc.h:139
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3285
#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:354
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:3279
#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:786
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
static void pg_atomic_init_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:226
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
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:256
LocalTransactionId lxid
Definition: proc.h:106

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 457 of file proc.c.

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

Referenced by InitPostgres().

458 {
459  Assert(MyProc != NULL);
460 
461  /*
462  * Add our PGPROC to the PGPROC array in shared memory.
463  */
465 
466  /*
467  * Arrange to clean that up at backend exit.
468  */
470 }
static void RemoveProcFromArray(int code, Datum arg)
Definition: proc.c:781
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:275

◆ 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  /*
273  * Save pointers to the blocks of PGPROC structures reserved for auxiliary
274  * processes and prepared transactions.
275  */
276  AuxiliaryProcs = &procs[MaxBackends];
278 
279  /* Create ProcStructLock spinlock, too */
280  ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
282 }
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:134
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:131
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:252
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 671 of file proc.c.

Referenced by RecoveryConflictInterrupt().

672 {
673  if (lockAwaited == NULL)
674  return false;
675 
676  return true;
677 }
static LOCALLOCK * lockAwaited
Definition: proc.c:85

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 688 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().

689 {
690  LWLock *partitionLock;
691  DisableTimeoutParams timeouts[2];
692 
693  HOLD_INTERRUPTS();
694 
696 
697  /* Nothing to do if we weren't waiting for a lock */
698  if (lockAwaited == NULL)
699  {
701  return;
702  }
703 
704  /*
705  * Turn off the deadlock and lock timeout timers, if they are still
706  * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
707  * indicator flag, since this function is executed before
708  * ProcessInterrupts when responding to SIGINT; else we'd lose the
709  * knowledge that the SIGINT came from a lock timeout and not an external
710  * source.
711  */
712  timeouts[0].id = DEADLOCK_TIMEOUT;
713  timeouts[0].keep_indicator = false;
714  timeouts[1].id = LOCK_TIMEOUT;
715  timeouts[1].keep_indicator = true;
716  disable_timeouts(timeouts, 2);
717 
718  /* Unlink myself from the wait queue, if on it (might not be anymore!) */
719  partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
720  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
721 
722  if (MyProc->links.next != NULL)
723  {
724  /* We could not have been granted the lock yet */
726  }
727  else
728  {
729  /*
730  * Somebody kicked us off the lock queue already. Perhaps they
731  * granted us the lock, or perhaps they detected a deadlock. If they
732  * did grant us the lock, we'd better remember it in our local lock
733  * table.
734  */
735  if (MyProc->waitStatus == STATUS_OK)
737  }
738 
739  lockAwaited = NULL;
740 
741  LWLockRelease(partitionLock);
742 
744 }
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:117
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:115

◆ 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:134
#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:134
#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 792 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().

793 {
794  PGPROC *proc;
795  PGPROC *volatile *procgloballist;
796 
797  Assert(MyProc != NULL);
798 
799  /* Make sure we're out of the sync rep lists */
801 
802 #ifdef USE_ASSERT_CHECKING
803  {
804  int i;
805 
806  /* Last process should have released all locks. */
807  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
809  }
810 #endif
811 
812  /*
813  * Release any LW locks I am holding. There really shouldn't be any, but
814  * it's cheap to check again before we cut the knees off the LWLock
815  * facility by releasing our PGPROC ...
816  */
818 
819  /* Cancel any pending condition variable sleep, too */
821 
822  /* Make sure active replication slots are released */
823  if (MyReplicationSlot != NULL)
825 
826  /* Also cleanup all the temporary slots. */
828 
829  /*
830  * Detach from any lock group of which we are a member. If the leader
831  * exist before all other group members, it's PGPROC will remain allocated
832  * until the last group process exits; that process must return the
833  * leader's PGPROC to the appropriate list.
834  */
835  if (MyProc->lockGroupLeader != NULL)
836  {
837  PGPROC *leader = MyProc->lockGroupLeader;
838  LWLock *leader_lwlock = LockHashPartitionLockByProc(leader);
839 
840  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
843  if (dlist_is_empty(&leader->lockGroupMembers))
844  {
845  leader->lockGroupLeader = NULL;
846  if (leader != MyProc)
847  {
848  procgloballist = leader->procgloballist;
849 
850  /* Leader exited first; return its PGPROC. */
852  leader->links.next = (SHM_QUEUE *) *procgloballist;
853  *procgloballist = leader;
855  }
856  }
857  else if (leader != MyProc)
858  MyProc->lockGroupLeader = NULL;
859  LWLockRelease(leader_lwlock);
860  }
861 
862  /*
863  * Reset MyLatch to the process local one. This is so that signal
864  * handlers et al can continue using the latch after the shared latch
865  * isn't ours anymore. After that clear MyProc and disown the shared
866  * latch.
867  */
869  proc = MyProc;
870  MyProc = NULL;
871  DisownLatch(&proc->procLatch);
872 
873  procgloballist = proc->procgloballist;
875 
876  /*
877  * If we're still a member of a locking group, that means we're a leader
878  * which has somehow exited before its children. The last remaining child
879  * will release our PGPROC. Otherwise, release it now.
880  */
881  if (proc->lockGroupLeader == NULL)
882  {
883  /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
885 
886  /* Return PGPROC structure (and semaphore) to appropriate freelist */
887  proc->links.next = (SHM_QUEUE *) *procgloballist;
888  *procgloballist = proc;
889  }
890 
891  /* Update shared estimate of spins_per_delay */
893 
895 
896  /*
897  * This process is no longer present in shared memory in any meaningful
898  * way, so tell the postmaster we've cleaned up acceptably well. (XXX
899  * autovac launcher should be included here someday)
900  */
903 
904  /* wake autovac launcher if needed -- see comments in FreeWorkerInfo */
905  if (AutovacuumLauncherPid != 0)
907 }
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:437
#define SIGUSR2
Definition: win32_port.h:178
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:373
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:108
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:3279
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:361
void DisownLatch(volatile Latch *latch)
Definition: latch.c:308
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 1606 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().

1607 {
1608  PROC_QUEUE *waitQueue = &(lock->waitProcs);
1609  int queue_size = waitQueue->size;
1610  PGPROC *proc;
1611  LOCKMASK aheadRequests = 0;
1612 
1613  Assert(queue_size >= 0);
1614 
1615  if (queue_size == 0)
1616  return;
1617 
1618  proc = (PGPROC *) waitQueue->links.next;
1619 
1620  while (queue_size-- > 0)
1621  {
1622  LOCKMODE lockmode = proc->waitLockMode;
1623 
1624  /*
1625  * Waken if (a) doesn't conflict with requests of earlier waiters, and
1626  * (b) doesn't conflict with already-held locks.
1627  */
1628  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1629  LockCheckConflicts(lockMethodTable,
1630  lockmode,
1631  lock,
1632  proc->waitProcLock) == STATUS_OK)
1633  {
1634  /* OK to waken */
1635  GrantLock(lock, proc->waitProcLock, lockmode);
1636  proc = ProcWakeup(proc, STATUS_OK);
1637 
1638  /*
1639  * ProcWakeup removes proc from the lock's waiting process queue
1640  * and returns the next proc in chain; don't use proc's next-link,
1641  * because it's been cleared.
1642  */
1643  }
1644  else
1645  {
1646  /*
1647  * Cannot wake this guy. Remember his request for later checks.
1648  */
1649  aheadRequests |= LOCKBIT_ON(lockmode);
1650  proc = (PGPROC *) proc->links.next;
1651  }
1652  }
1653 
1654  Assert(waitQueue->size >= 0);
1655 }
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:1570
Definition: proc.h:95

◆ ProcQueueInit()

void ProcQueueInit ( PROC_QUEUE queue)

Definition at line 1015 of file proc.c.

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

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

1016 {
1017  SHMQueueInit(&(queue->links));
1018  queue->size = 0;
1019 }
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 764 of file proc.c.

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

Referenced by ResourceOwnerReleaseInternal().

765 {
766  if (!MyProc)
767  return;
768  /* If waiting, get off wait queue (should only be needed after error) */
770  /* Release standard locks, including session-level if aborting */
772  /* Release transaction-level advisory locks */
774 }
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:688
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2089

◆ ProcSendSignal()

void ProcSendSignal ( int  pid)

Definition at line 1788 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().

1789 {
1790  PGPROC *proc = NULL;
1791 
1792  if (RecoveryInProgress())
1793  {
1795 
1796  /*
1797  * Check to see whether it is the Startup process we wish to signal.
1798  * This call is made by the buffer manager when it wishes to wake up a
1799  * process that has been waiting for a pin in so it can obtain a
1800  * cleanup lock using LockBufferForCleanup(). Startup is not a normal
1801  * backend, so BackendPidGetProc() will not return any pid at all. So
1802  * we remember the information for this special case.
1803  */
1804  if (pid == ProcGlobal->startupProcPid)
1805  proc = ProcGlobal->startupProc;
1806 
1808  }
1809 
1810  if (proc == NULL)
1811  proc = BackendPidGetProc(pid);
1812 
1813  if (proc != NULL)
1814  {
1815  SetLatch(&proc->procLatch);
1816  }
1817 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:2365
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool RecoveryInProgress(void)
Definition: xlog.c:8082
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:414
PGPROC * startupProc
Definition: proc.h:269
Definition: proc.h:95

◆ ProcSleep()

int ProcSleep ( LOCALLOCK locallock,
LockMethod  lockMethodTable 
)

Definition at line 1039 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, and WL_LATCH_SET.

Referenced by WaitOnLock().

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

◆ ProcWaitForSignal()

void ProcWaitForSignal ( uint32  wait_event_info)

Definition at line 1777 of file proc.c.

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

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

1778 {
1779  WaitLatch(MyLatch, WL_LATCH_SET, 0, wait_event_info);
1782 }
void ResetLatch(volatile Latch *latch)
Definition: latch.c:497
int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:336
struct Latch * MyLatch
Definition: globals.c:53
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define WL_LATCH_SET
Definition: latch.h:124

◆ ProcWakeup()

PGPROC* ProcWakeup ( PGPROC proc,
int  waitStatus 
)

Definition at line 1570 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().

1571 {
1572  PGPROC *retProc;
1573 
1574  /* Proc should be sleeping ... */
1575  if (proc->links.prev == NULL ||
1576  proc->links.next == NULL)
1577  return NULL;
1578  Assert(proc->waitStatus == STATUS_WAITING);
1579 
1580  /* Save next process before we zap the list link */
1581  retProc = (PGPROC *) proc->links.next;
1582 
1583  /* Remove process from wait queue */
1584  SHMQueueDelete(&(proc->links));
1585  (proc->waitLock->waitProcs.size)--;
1586 
1587  /* Clean up process' state and pass it the ok/fail signal */
1588  proc->waitLock = NULL;
1589  proc->waitProcLock = NULL;
1590  proc->waitStatus = waitStatus;
1591 
1592  /* And awaken it */
1593  SetLatch(&proc->procLatch);
1594 
1595  return retProc;
1596 }
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:414
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 604 of file proc.c.

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

Referenced by StartupXLOG().

605 {
607 
610 
612 }
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 781 of file proc.c.

References Assert, InvalidTransactionId, and ProcArrayRemove().

Referenced by InitProcessPhase2().

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

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 622 of file proc.c.

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

623 {
624  /* use volatile pointer to prevent code rearrangement */
625  volatile PROC_HDR *procglobal = ProcGlobal;
626 
627  procglobal->startupBufferPinWaitBufId = bufid;
628 }
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().