PostgreSQL Source Code  git master
proc.h File Reference
#include "access/clog.h"
#include "access/xlogdefs.h"
#include "lib/ilist.h"
#include "storage/latch.h"
#include "storage/lock.h"
#include "storage/pg_sema.h"
#include "storage/proclist_types.h"
Include dependency graph for proc.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  XidCacheStatus
 
struct  XidCache
 
struct  PGPROC
 
struct  PROC_HDR
 

Macros

#define PGPROC_MAX_CACHED_SUBXIDS   64 /* XXX guessed-at value */
 
#define PROC_IS_AUTOVACUUM   0x01 /* is it an autovac worker? */
 
#define PROC_IN_VACUUM   0x02 /* currently running lazy vacuum */
 
#define PROC_IN_SAFE_IC
 
#define PROC_VACUUM_FOR_WRAPAROUND   0x08 /* set by autovac only */
 
#define PROC_IN_LOGICAL_DECODING
 
#define PROC_AFFECTS_ALL_HORIZONS
 
#define PROC_VACUUM_STATE_MASK    (PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND)
 
#define PROC_XMIN_FLAGS   (PROC_IN_VACUUM | PROC_IN_SAFE_IC)
 
#define FP_LOCK_SLOTS_PER_BACKEND   16
 
#define INVALID_PGPROCNO   PG_INT32_MAX
 
#define DELAY_CHKPT_START   (1<<0)
 
#define DELAY_CHKPT_COMPLETE   (1<<1)
 
#define GetPGProcByNumber(n)   (&ProcGlobal->allProcs[(n)])
 
#define NUM_AUXILIARY_PROCS   5
 

Typedefs

typedef struct XidCacheStatus XidCacheStatus
 
typedef struct PROC_HDR PROC_HDR
 

Enumerations

enum  ProcWaitStatus { PROC_WAIT_STATUS_OK , PROC_WAIT_STATUS_WAITING , PROC_WAIT_STATUS_ERROR }
 

Functions

int ProcGlobalSemas (void)
 
Size ProcGlobalShmemSize (void)
 
void InitProcGlobal (void)
 
void InitProcess (void)
 
void InitProcessPhase2 (void)
 
void InitAuxiliaryProcess (void)
 
void SetStartupBufferPinWaitBufId (int bufid)
 
int GetStartupBufferPinWaitBufId (void)
 
bool HaveNFreeProcs (int n, int *nfree)
 
void ProcReleaseLocks (bool isCommit)
 
ProcWaitStatus ProcSleep (LOCALLOCK *locallock, LockMethod lockMethodTable)
 
void ProcWakeup (PGPROC *proc, ProcWaitStatus waitStatus)
 
void ProcLockWakeup (LockMethod lockMethodTable, LOCK *lock)
 
void CheckDeadLockAlert (void)
 
bool IsWaitingForLock (void)
 
void LockErrorCleanup (void)
 
void ProcWaitForSignal (uint32 wait_event_info)
 
void ProcSendSignal (int pgprocno)
 
PGPROCAuxiliaryPidGetProc (int pid)
 
void BecomeLockGroupLeader (void)
 
bool BecomeLockGroupMember (PGPROC *leader, int pid)
 

Variables

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

Macro Definition Documentation

◆ DELAY_CHKPT_COMPLETE

#define DELAY_CHKPT_COMPLETE   (1<<1)

Definition at line 120 of file proc.h.

◆ DELAY_CHKPT_START

#define DELAY_CHKPT_START   (1<<0)

Definition at line 119 of file proc.h.

◆ FP_LOCK_SLOTS_PER_BACKEND

#define FP_LOCK_SLOTS_PER_BACKEND   16

Definition at line 79 of file proc.h.

◆ GetPGProcByNumber

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

Definition at line 408 of file proc.h.

◆ INVALID_PGPROCNO

#define INVALID_PGPROCNO   PG_INT32_MAX

Definition at line 85 of file proc.h.

◆ NUM_AUXILIARY_PROCS

#define NUM_AUXILIARY_PROCS   5

Definition at line 418 of file proc.h.

◆ PGPROC_MAX_CACHED_SUBXIDS

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

Definition at line 38 of file proc.h.

◆ PROC_AFFECTS_ALL_HORIZONS

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

Definition at line 61 of file proc.h.

◆ PROC_IN_LOGICAL_DECODING

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

Definition at line 60 of file proc.h.

◆ PROC_IN_SAFE_IC

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

Definition at line 58 of file proc.h.

◆ PROC_IN_VACUUM

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

Definition at line 57 of file proc.h.

◆ PROC_IS_AUTOVACUUM

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

Definition at line 56 of file proc.h.

◆ PROC_VACUUM_FOR_WRAPAROUND

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

Definition at line 59 of file proc.h.

◆ PROC_VACUUM_STATE_MASK

#define PROC_VACUUM_STATE_MASK    (PROC_IN_VACUUM | PROC_IN_SAFE_IC | PROC_VACUUM_FOR_WRAPAROUND)

Definition at line 64 of file proc.h.

◆ PROC_XMIN_FLAGS

#define PROC_XMIN_FLAGS   (PROC_IN_VACUUM | PROC_IN_SAFE_IC)

Definition at line 71 of file proc.h.

Typedef Documentation

◆ PROC_HDR

typedef struct PROC_HDR PROC_HDR

◆ XidCacheStatus

Enumeration Type Documentation

◆ ProcWaitStatus

Enumerator
PROC_WAIT_STATUS_OK 
PROC_WAIT_STATUS_WAITING 
PROC_WAIT_STATUS_ERROR 

Definition at line 122 of file proc.h.

129 {

Function Documentation

◆ AuxiliaryPidGetProc()

PGPROC* AuxiliaryPidGetProc ( int  pid)

Definition at line 1000 of file proc.c.

1001 {
1002  PGPROC *result = NULL;
1003  int index;
1004 
1005  if (pid == 0) /* never match dummy PGPROCs */
1006  return NULL;
1007 
1008  for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
1009  {
1010  PGPROC *proc = &AuxiliaryProcs[index];
1011 
1012  if (proc->pid == pid)
1013  {
1014  result = proc;
1015  break;
1016  }
1017  }
1018  return result;
1019 }
#define NUM_AUXILIARY_PROCS
Definition: proc.h:418
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:79
Definition: proc.h:162
int pid
Definition: proc.h:186
Definition: type.h:95

References AuxiliaryProcs, NUM_AUXILIARY_PROCS, and PGPROC::pid.

Referenced by pg_log_backend_memory_contexts(), and pg_stat_get_activity().

◆ BecomeLockGroupLeader()

void BecomeLockGroupLeader ( void  )

Definition at line 1859 of file proc.c.

1860 {
1861  LWLock *leader_lwlock;
1862 
1863  /* If we already did it, we don't need to do it again. */
1864  if (MyProc->lockGroupLeader == MyProc)
1865  return;
1866 
1867  /* We had better not be a follower. */
1868  Assert(MyProc->lockGroupLeader == NULL);
1869 
1870  /* Create single-member group, containing only ourselves. */
1871  leader_lwlock = LockHashPartitionLockByProc(MyProc);
1872  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1875  LWLockRelease(leader_lwlock);
1876 }
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:347
Assert(fmt[strlen(fmt) - 1] !='\n')
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:542
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1195
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1808
@ LW_EXCLUSIVE
Definition: lwlock.h:116
PGPROC * MyProc
Definition: proc.c:66
Definition: lwlock.h:41
dlist_head lockGroupMembers
Definition: proc.h:296
dlist_node lockGroupLink
Definition: proc.h:297
PGPROC * lockGroupLeader
Definition: proc.h:295

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

Referenced by LaunchParallelWorkers().

◆ BecomeLockGroupMember()

bool BecomeLockGroupMember ( PGPROC leader,
int  pid 
)

Definition at line 1889 of file proc.c.

1890 {
1891  LWLock *leader_lwlock;
1892  bool ok = false;
1893 
1894  /* Group leader can't become member of group */
1895  Assert(MyProc != leader);
1896 
1897  /* Can't already be a member of a group */
1898  Assert(MyProc->lockGroupLeader == NULL);
1899 
1900  /* PID must be valid. */
1901  Assert(pid != 0);
1902 
1903  /*
1904  * Get lock protecting the group fields. Note LockHashPartitionLockByProc
1905  * accesses leader->pgprocno in a PGPROC that might be free. This is safe
1906  * because all PGPROCs' pgprocno fields are set during shared memory
1907  * initialization and never change thereafter; so we will acquire the
1908  * correct lock even if the leader PGPROC is in process of being recycled.
1909  */
1910  leader_lwlock = LockHashPartitionLockByProc(leader);
1911  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1912 
1913  /* Is this the leader we're looking for? */
1914  if (leader->pid == pid && leader->lockGroupLeader == leader)
1915  {
1916  /* OK, join the group */
1917  ok = true;
1918  MyProc->lockGroupLeader = leader;
1920  }
1921  LWLockRelease(leader_lwlock);
1922 
1923  return ok;
1924 }
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364

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

Referenced by ParallelWorkerMain().

◆ CheckDeadLockAlert()

void CheckDeadLockAlert ( void  )

Definition at line 1806 of file proc.c.

1807 {
1808  int save_errno = errno;
1809 
1810  got_deadlock_timeout = true;
1811 
1812  /*
1813  * Have to set the latch again, even if handle_sig_alarm already did. Back
1814  * then got_deadlock_timeout wasn't yet set... It's unlikely that this
1815  * ever would be a problem, but setting a set latch again is cheap.
1816  *
1817  * Note that, when this function runs inside procsignal_sigusr1_handler(),
1818  * the handler function sets the latch again after the latch is set here.
1819  */
1820  SetLatch(MyLatch);
1821  errno = save_errno;
1822 }
struct Latch * MyLatch
Definition: globals.c:58
void SetLatch(Latch *latch)
Definition: latch.c:633
static volatile sig_atomic_t got_deadlock_timeout
Definition: proc.c:88

References got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres(), and ProcessRecoveryConflictInterrupt().

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 666 of file proc.c.

667 {
668  /* use volatile pointer to prevent code rearrangement */
669  volatile PROC_HDR *procglobal = ProcGlobal;
670 
671  return procglobal->startupBufferPinWaitBufId;
672 }
PROC_HDR * ProcGlobal
Definition: proc.c:78
Definition: proc.h:360
int startupBufferPinWaitBufId
Definition: proc.h:400

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and ProcessRecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n,
int *  nfree 
)

Definition at line 682 of file proc.c.

683 {
684  dlist_iter iter;
685 
686  Assert(n > 0);
687  Assert(nfree);
688 
690 
691  *nfree = 0;
693  {
694  (*nfree)++;
695  if (*nfree == n)
696  break;
697  }
698 
700 
701  return (*nfree == n);
702 }
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:75
dlist_head freeProcs
Definition: proc.h:382

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 519 of file proc.c.

520 {
521  PGPROC *auxproc;
522  int proctype;
523 
524  /*
525  * ProcGlobal should be set up already (if we are a backend, we inherit
526  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
527  */
528  if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
529  elog(PANIC, "proc header uninitialized");
530 
531  if (MyProc != NULL)
532  elog(ERROR, "you already exist");
533 
534  /*
535  * We use the ProcStructLock to protect assignment and releasing of
536  * AuxiliaryProcs entries.
537  *
538  * While we are holding the ProcStructLock, also copy the current shared
539  * estimate of spins_per_delay to local storage.
540  */
542 
544 
545  /*
546  * Find a free auxproc ... *big* trouble if there isn't one ...
547  */
548  for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
549  {
550  auxproc = &AuxiliaryProcs[proctype];
551  if (auxproc->pid == 0)
552  break;
553  }
554  if (proctype >= NUM_AUXILIARY_PROCS)
555  {
557  elog(FATAL, "all AuxiliaryProcs are in use");
558  }
559 
560  /* Mark auxiliary proc as in use by me */
561  /* use volatile pointer to prevent code rearrangement */
562  ((volatile PGPROC *) auxproc)->pid = MyProcPid;
563 
564  MyProc = auxproc;
565 
567 
568  /*
569  * Initialize all fields of MyProc, except for those previously
570  * initialized by InitProcGlobal.
571  */
575  MyProc->fpVXIDLock = false;
584  MyProc->delayChkptFlags = 0;
585  MyProc->statusFlags = 0;
587  MyProc->lwWaitMode = 0;
588  MyProc->waitLock = NULL;
589  MyProc->waitProcLock = NULL;
591 #ifdef USE_ASSERT_CHECKING
592  {
593  int i;
594 
595  /* Last process should have released all locks. */
596  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
598  }
599 #endif
600 
601  /*
602  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
603  * on it. That allows us to repoint the process latch, which so far
604  * points to process local one, to the shared one.
605  */
608 
609  /* now that we have a proc, report wait events to shared memory */
611 
612  /* Check that group locking fields are in a proper initial state. */
613  Assert(MyProc->lockGroupLeader == NULL);
615 
616  /*
617  * We might be reusing a semaphore that belonged to a failed process. So
618  * be careful and reinitialize its value here. (This is not strictly
619  * necessary anymore, but seems like a good idea for cleanliness.)
620  */
622 
623  /*
624  * Arrange to clean up at process exit.
625  */
627 
628  /*
629  * Now that we have a PGPROC, we could try to acquire lightweight locks.
630  * Initialize local state needed for them. (Heavyweight locks cannot be
631  * acquired in aux processes.)
632  */
634 
635 #ifdef EXEC_BACKEND
636 
637  /*
638  * Initialize backend-local pointers to all the shared data structures.
639  * (We couldn't do this until now because it needs LWLocks.)
640  */
641  if (IsUnderPostmaster)
642  AttachSharedMemoryStructs();
643 #endif
644 }
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:433
#define InvalidBackendId
Definition: backendid.h:23
#define FATAL
Definition: elog.h:41
#define PANIC
Definition: elog.h:42
#define ERROR
Definition: elog.h:39
int MyProcPid
Definition: globals.c:44
bool IsUnderPostmaster
Definition: globals.c:115
bool IsBackgroundWorker
Definition: globals.c:117
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
static void dlist_node_init(dlist_node *node)
Definition: ilist.h:325
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
int i
Definition: isn.c:73
void OwnLatch(Latch *latch)
Definition: latch.c:464
#define InvalidLocalTransactionId
Definition: lock.h:65
void InitLWLockAccess(void)
Definition: lwlock.c:581
@ LW_WS_NOT_WAITING
Definition: lwlock.h:29
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:99
void SwitchToSharedLatch(void)
Definition: miscinit.c:221
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:295
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
@ PROC_WAIT_STATUS_OK
Definition: proc.h:124
void set_spins_per_delay(int shared_spins_per_delay)
Definition: s_lock.c:207
static void AuxiliaryProcKill(int code, Datum arg)
Definition: proc.c:952
TransactionId xmin
Definition: proc.h:178
LocalTransactionId lxid
Definition: proc.h:183
PROCLOCK * waitProcLock
Definition: proc.h:224
uint8 lwWaitMode
Definition: proc.h:215
uint32 wait_event_info
Definition: proc.h:270
uint8 statusFlags
Definition: proc.h:233
Oid databaseId
Definition: proc.h:198
pg_atomic_uint64 waitStart
Definition: proc.h:228
bool fpVXIDLock
Definition: proc.h:287
BackendId backendId
Definition: proc.h:197
bool isBackgroundWorker
Definition: proc.h:204
LOCK * waitLock
Definition: proc.h:223
TransactionId xid
Definition: proc.h:173
int delayChkptFlags
Definition: proc.h:231
LocalTransactionId fpLocalTransactionId
Definition: proc.h:288
PGSemaphore sem
Definition: proc.h:167
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:252
Oid roleId
Definition: proc.h:199
ProcWaitStatus waitStatus
Definition: proc.h:168
Oid tempNamespaceId
Definition: proc.h:201
dlist_node links
Definition: proc.h:164
uint8 lwWaiting
Definition: proc.h:214
Latch procLatch
Definition: proc.h:170
int spins_per_delay
Definition: proc.h:398
#define InvalidTransactionId
Definition: transam.h:31
void pgstat_set_wait_event_storage(uint32 *wait_event_info)
Definition: wait_event.c:316

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

Referenced by AuxiliaryProcessMain().

◆ InitProcess()

void InitProcess ( void  )

Definition at line 297 of file proc.c.

298 {
299  dlist_head *procgloballist;
300 
301  /*
302  * ProcGlobal should be set up already (if we are a backend, we inherit
303  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
304  */
305  if (ProcGlobal == NULL)
306  elog(PANIC, "proc header uninitialized");
307 
308  if (MyProc != NULL)
309  elog(ERROR, "you already exist");
310 
311  /* Decide which list should supply our PGPROC. */
313  procgloballist = &ProcGlobal->autovacFreeProcs;
314  else if (IsBackgroundWorker)
315  procgloballist = &ProcGlobal->bgworkerFreeProcs;
316  else if (am_walsender)
317  procgloballist = &ProcGlobal->walsenderFreeProcs;
318  else
319  procgloballist = &ProcGlobal->freeProcs;
320 
321  /*
322  * Try to get a proc struct from the appropriate free list. If this
323  * fails, we must be out of PGPROC structures (not to mention semaphores).
324  *
325  * While we are holding the ProcStructLock, also copy the current shared
326  * estimate of spins_per_delay to local storage.
327  */
329 
331 
332  if (!dlist_is_empty(procgloballist))
333  {
334  MyProc = (PGPROC *) dlist_pop_head_node(procgloballist);
336  }
337  else
338  {
339  /*
340  * If we reach here, all the PGPROCs are in use. This is one of the
341  * possible places to detect "too many backends", so give the standard
342  * error message. XXX do we need to give a different failure message
343  * in the autovacuum case?
344  */
346  if (am_walsender)
347  ereport(FATAL,
348  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
349  errmsg("number of requested standby connections exceeds max_wal_senders (currently %d)",
350  max_wal_senders)));
351  ereport(FATAL,
352  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
353  errmsg("sorry, too many clients already")));
354  }
355 
356  /*
357  * Cross-check that the PGPROC is of the type we expect; if this were not
358  * the case, it would get returned to the wrong list.
359  */
360  Assert(MyProc->procgloballist == procgloballist);
361 
362  /*
363  * Now that we have a PGPROC, mark ourselves as an active postmaster
364  * child; this is so that the postmaster can detect it if we exit without
365  * cleaning up. (XXX autovac launcher currently doesn't participate in
366  * this; it probably should.)
367  */
370 
371  /*
372  * Initialize all fields of MyProc, except for those previously
373  * initialized by InitProcGlobal.
374  */
378  MyProc->fpVXIDLock = false;
382  MyProc->pid = MyProcPid;
383  /* backendId, databaseId and roleId will be filled in later */
389  MyProc->delayChkptFlags = 0;
390  MyProc->statusFlags = 0;
391  /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
395  MyProc->lwWaitMode = 0;
396  MyProc->waitLock = NULL;
397  MyProc->waitProcLock = NULL;
399 #ifdef USE_ASSERT_CHECKING
400  {
401  int i;
402 
403  /* Last process should have released all locks. */
404  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
406  }
407 #endif
409 
410  /* Initialize fields for sync rep */
411  MyProc->waitLSN = 0;
414 
415  /* Initialize fields for group XID clearing. */
416  MyProc->procArrayGroupMember = false;
419 
420  /* Check that group locking fields are in a proper initial state. */
421  Assert(MyProc->lockGroupLeader == NULL);
423 
424  /* Initialize wait event information. */
425  MyProc->wait_event_info = 0;
426 
427  /* Initialize fields for group transaction status update. */
428  MyProc->clogGroupMember = false;
434 
435  /*
436  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
437  * on it. That allows us to repoint the process latch, which so far
438  * points to process local one, to the shared one.
439  */
442 
443  /* now that we have a proc, report wait events to shared memory */
445 
446  /*
447  * We might be reusing a semaphore that belonged to a failed process. So
448  * be careful and reinitialize its value here. (This is not strictly
449  * necessary anymore, but seems like a good idea for cleanliness.)
450  */
452 
453  /*
454  * Arrange to clean up at backend exit.
455  */
457 
458  /*
459  * Now that we have a PGPROC, we could try to acquire locks, so initialize
460  * local state needed for LWLocks, and the deadlock checker.
461  */
464 
465 #ifdef EXEC_BACKEND
466 
467  /*
468  * Initialize backend-local pointers to all the shared data structures.
469  * (We couldn't do this until now because it needs LWLocks.)
470  */
471  if (IsUnderPostmaster)
472  AttachSharedMemoryStructs();
473 #endif
474 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3364
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3370
#define IsAnyAutoVacuumProcess()
Definition: autovacuum.h:55
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:27
void InitDeadLockChecking(void)
Definition: deadlock.c:143
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
static dlist_node * dlist_pop_head_node(dlist_head *head)
Definition: ilist.h:450
void MarkPostmasterChildActive(void)
Definition: pmsignal.c:323
#define INVALID_PGPROCNO
Definition: proc.h:85
#define PROC_IS_AUTOVACUUM
Definition: proc.h:56
static void ProcKill(int code, Datum arg)
Definition: proc.c:829
bool procArrayGroupMember
Definition: proc.h:260
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:280
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:262
dlist_head * procgloballist
Definition: proc.h:165
bool recoveryConflictPending
Definition: proc.h:211
TransactionId clogGroupMemberXid
Definition: proc.h:275
int64 clogGroupMemberPage
Definition: proc.h:278
bool clogGroupMember
Definition: proc.h:273
XLogRecPtr waitLSN
Definition: proc.h:243
dlist_node syncRepLinks
Definition: proc.h:245
int syncRepState
Definition: proc.h:244
pg_atomic_uint32 clogGroupNext
Definition: proc.h:274
XidStatus clogGroupMemberXidStatus
Definition: proc.h:276
TransactionId procArrayGroupMemberXid
Definition: proc.h:268
dlist_head autovacFreeProcs
Definition: proc.h:384
dlist_head walsenderFreeProcs
Definition: proc.h:388
dlist_head bgworkerFreeProcs
Definition: proc.h:386
#define SYNC_REP_NOT_WAITING
Definition: syncrep.h:30
bool am_walsender
Definition: walsender.c:116
int max_wal_senders
Definition: walsender.c:122
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

References am_walsender, Assert(), PROC_HDR::autovacFreeProcs, PGPROC::backendId, PROC_HDR::bgworkerFreeProcs, PGPROC::clogGroupMember, PGPROC::clogGroupMemberLsn, PGPROC::clogGroupMemberPage, PGPROC::clogGroupMemberXid, PGPROC::clogGroupMemberXidStatus, PGPROC::clogGroupNext, PGPROC::databaseId, PGPROC::delayChkptFlags, dlist_is_empty(), dlist_node_init(), dlist_pop_head_node(), 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, LW_WS_NOT_WAITING, PGPROC::lwWaiting, PGPROC::lwWaitMode, PGPROC::lxid, MarkPostmasterChildActive(), max_wal_senders, MyProc, PGPROC::myProcLocks, MyProcPid, NUM_LOCK_PARTITIONS, on_shmem_exit(), OwnLatch(), PANIC, pg_atomic_read_u32(), pg_atomic_write_u64(), PGSemaphoreReset(), pgstat_set_wait_event_storage(), PGPROC::pid, PROC_IS_AUTOVACUUM, PROC_WAIT_STATUS_OK, PGPROC::procArrayGroupMember, PGPROC::procArrayGroupMemberXid, PGPROC::procArrayGroupNext, ProcGlobal, PGPROC::procgloballist, ProcKill(), PGPROC::procLatch, ProcStructLock, PGPROC::recoveryConflictPending, PGPROC::roleId, PGPROC::sem, set_spins_per_delay(), SpinLockAcquire, SpinLockRelease, PROC_HDR::spins_per_delay, PGPROC::statusFlags, SwitchToSharedLatch(), SYNC_REP_NOT_WAITING, PGPROC::syncRepLinks, PGPROC::syncRepState, PGPROC::tempNamespaceId, TRANSACTION_STATUS_IN_PROGRESS, PGPROC::wait_event_info, PGPROC::waitLock, PGPROC::waitLSN, PGPROC::waitProcLock, PGPROC::waitStart, PGPROC::waitStatus, PROC_HDR::walsenderFreeProcs, PGPROC::xid, and PGPROC::xmin.

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

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 484 of file proc.c.

485 {
486  Assert(MyProc != NULL);
487 
488  /*
489  * Add our PGPROC to the PGPROC array in shared memory.
490  */
492 
493  /*
494  * Arrange to clean that up at backend exit.
495  */
497 }
void ProcArrayAdd(PGPROC *proc)
Definition: procarray.c:469
static void RemoveProcFromArray(int code, Datum arg)
Definition: proc.c:818

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 157 of file proc.c.

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

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

Referenced by CreateOrAttachShmemStructs().

◆ IsWaitingForLock()

bool IsWaitingForLock ( void  )

Definition at line 708 of file proc.c.

709 {
710  if (lockAwaited == NULL)
711  return false;
712 
713  return true;
714 }
static LOCALLOCK * lockAwaited
Definition: proc.c:83

References lockAwaited.

Referenced by ProcessRecoveryConflictInterrupt().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 725 of file proc.c.

726 {
727  LWLock *partitionLock;
728  DisableTimeoutParams timeouts[2];
729 
730  HOLD_INTERRUPTS();
731 
733 
734  /* Nothing to do if we weren't waiting for a lock */
735  if (lockAwaited == NULL)
736  {
738  return;
739  }
740 
741  /*
742  * Turn off the deadlock and lock timeout timers, if they are still
743  * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
744  * indicator flag, since this function is executed before
745  * ProcessInterrupts when responding to SIGINT; else we'd lose the
746  * knowledge that the SIGINT came from a lock timeout and not an external
747  * source.
748  */
749  timeouts[0].id = DEADLOCK_TIMEOUT;
750  timeouts[0].keep_indicator = false;
751  timeouts[1].id = LOCK_TIMEOUT;
752  timeouts[1].keep_indicator = true;
753  disable_timeouts(timeouts, 2);
754 
755  /* Unlink myself from the wait queue, if on it (might not be anymore!) */
756  partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
757  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
758 
760  {
761  /* We could not have been granted the lock yet */
763  }
764  else
765  {
766  /*
767  * Somebody kicked us off the lock queue already. Perhaps they
768  * granted us the lock, or perhaps they detected a deadlock. If they
769  * did grant us the lock, we'd better remember it in our local lock
770  * table.
771  */
774  }
775 
776  lockAwaited = NULL;
777 
778  LWLockRelease(partitionLock);
779 
781 }
static bool dlist_node_is_detached(const dlist_node *node)
Definition: ilist.h:525
void GrantAwaitedLock(void)
Definition: lock.c:1757
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1869
void AbortStrongLockAcquire(void)
Definition: lock.c:1728
#define LockHashPartitionLock(hashcode)
Definition: lock.h:527
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:134
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:132
TimeoutId id
Definition: timeout.h:70
uint32 hashcode
Definition: lock.h:432
void disable_timeouts(const DisableTimeoutParams *timeouts, int count)
Definition: timeout.c:722
@ LOCK_TIMEOUT
Definition: timeout.h:28
@ DEADLOCK_TIMEOUT
Definition: timeout.h:27

References AbortStrongLockAcquire(), DEADLOCK_TIMEOUT, disable_timeouts(), dlist_node_is_detached(), GrantAwaitedLock(), LOCALLOCK::hashcode, HOLD_INTERRUPTS, DisableTimeoutParams::id, DisableTimeoutParams::keep_indicator, PGPROC::links, LOCK_TIMEOUT, lockAwaited, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), RESUME_INTERRUPTS, and PGPROC::waitStatus.

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

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 122 of file proc.c.

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

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 100 of file proc.c.

101 {
102  Size size = 0;
103  Size TotalProcs =
105 
106  /* ProcGlobal */
107  size = add_size(size, sizeof(PROC_HDR));
108  size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
109  size = add_size(size, sizeof(slock_t));
110 
111  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
112  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
113  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
114 
115  return size;
116 }
size_t Size
Definition: c.h:594
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519

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

Referenced by CalculateShmemSize().

◆ ProcLockWakeup()

void ProcLockWakeup ( LockMethod  lockMethodTable,
LOCK lock 
)

Definition at line 1672 of file proc.c.

1673 {
1674  dclist_head *waitQueue = &lock->waitProcs;
1675  LOCKMASK aheadRequests = 0;
1676  dlist_mutable_iter miter;
1677 
1678  if (dclist_is_empty(waitQueue))
1679  return;
1680 
1681  dclist_foreach_modify(miter, waitQueue)
1682  {
1683  PGPROC *proc = dlist_container(PGPROC, links, miter.cur);
1684  LOCKMODE lockmode = proc->waitLockMode;
1685 
1686  /*
1687  * Waken if (a) doesn't conflict with requests of earlier waiters, and
1688  * (b) doesn't conflict with already-held locks.
1689  */
1690  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1691  !LockCheckConflicts(lockMethodTable, lockmode, lock,
1692  proc->waitProcLock))
1693  {
1694  /* OK to waken */
1695  GrantLock(lock, proc->waitProcLock, lockmode);
1696  /* removes proc from the lock's waiting process queue */
1698  }
1699  else
1700  {
1701  /*
1702  * Lock conflicts: Don't wake, but remember requested mode for
1703  * later checks.
1704  */
1705  aheadRequests |= LOCKBIT_ON(lockmode);
1706  }
1707  }
1708 }
static bool dclist_is_empty(const dclist_head *head)
Definition: ilist.h:682
#define dclist_foreach_modify(iter, lhead)
Definition: ilist.h:973
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1526
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1397
#define LOCKBIT_ON(lockmode)
Definition: lock.h:84
int LOCKMODE
Definition: lockdefs.h:26
int LOCKMASK
Definition: lockdefs.h:25
void ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition: proc.c:1644
dclist_head waitProcs
Definition: lock.h:317
const LOCKMASK * conflictTab
Definition: lock.h:111
LOCKMODE waitLockMode
Definition: proc.h:225
dlist_node * cur
Definition: ilist.h:200
static struct link * links
Definition: zic.c:299

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

Referenced by CleanUpLock(), and DeadLockCheck().

◆ ProcReleaseLocks()

void ProcReleaseLocks ( bool  isCommit)

Definition at line 801 of file proc.c.

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

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( int  pgprocno)

Definition at line 1844 of file proc.c.

1845 {
1846  if (pgprocno < 0 || pgprocno >= ProcGlobal->allProcCount)
1847  elog(ERROR, "pgprocno out of range");
1848 
1849  SetLatch(&ProcGlobal->allProcs[pgprocno].procLatch);
1850 }

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

Referenced by ReleasePredicateLocks(), and UnpinBufferNoOwner().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock,
LockMethod  lockMethodTable 
)

Definition at line 1039 of file proc.c.

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

References AccessExclusiveLock, appendStringInfo(), Assert(), buf, CHECK_FOR_INTERRUPTS, CheckDeadLock(), CheckRecoveryConflictDeadlock(), LockMethodData::conflictTab, dlist_iter::cur, StringInfoData::data, dclist_foreach, dclist_insert_before(), dclist_is_empty(), dclist_push_tail(), deadlock_state, DEADLOCK_TIMEOUT, DeadlockTimeout, DEBUG1, EnableTimeoutParams::delay_ms, DescribeLockTag(), disable_timeout(), disable_timeouts(), dlist_container, dlist_foreach, DS_BLOCKED_BY_AUTOVACUUM, DS_HARD_DEADLOCK, DS_NO_DEADLOCK, DS_NOT_YET_CHECKED, DS_SOFT_DEADLOCK, enable_timeout_after(), enable_timeouts(), ereport, errdetail_log(), errdetail_log_plural(), errmsg(), errmsg_internal(), get_timeout_start_time(), GetBlockingAutoVacuumPgproc(), GetCurrentTimestamp(), GetLockConflicts(), GetLockmodeName(), got_deadlock_timeout, GrantAwaitedLock(), GrantLock(), PROCLOCK::groupLeader, LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, EnableTimeoutParams::id, DisableTimeoutParams::id, InHotStandby, initStringInfo(), InRecovery, DisableTimeoutParams::keep_indicator, kill, PGPROC::links, links, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_TIMEOUT, lockAwaited, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, LOCKTAG::locktag_lockmethodid, LOCKTAG::locktag_type, LockTimeout, LOG, log_lock_waits, log_recovery_conflict_waits, LogRecoveryConflict(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), message_level_is_interesting(), LOCALLOCKTAG::mode, MyLatch, MyProc, PROCLOCKTAG::myProc, MyProcPid, now(), pfree(), pg_atomic_write_u64(), PG_WAIT_LOCK, PGPROC::pgxactoff, PGPROC::pid, PROC_IS_AUTOVACUUM, PROC_VACUUM_FOR_WRAPAROUND, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_OK, PROC_WAIT_STATUS_WAITING, ProcGlobal, LOCALLOCK::proclock, LOCK::procLocks, PROCSIG_RECOVERY_CONFLICT_LOCK, RecoveryInProgress(), RememberSimpleDeadLock(), RemoveFromWaitQueue(), ResetLatch(), ResolveRecoveryConflictWithLock(), PROC_HDR::statusFlags, LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, TimestampDifference(), TimestampDifferenceExceeds(), TMPARAM_AFTER, EnableTimeoutParams::type, WaitLatch(), PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, PGPROC::waitStart, PGPROC::waitStatus, WARNING, WL_EXIT_ON_PM_DEATH, and WL_LATCH_SET.

Referenced by WaitOnLock().

◆ ProcWaitForSignal()

void ProcWaitForSignal ( uint32  wait_event_info)

◆ ProcWakeup()

void ProcWakeup ( PGPROC proc,
ProcWaitStatus  waitStatus 
)

Definition at line 1644 of file proc.c.

1645 {
1646  if (dlist_node_is_detached(&proc->links))
1647  return;
1648 
1650 
1651  /* Remove process from wait queue */
1653 
1654  /* Clean up process' state and pass it the ok/fail signal */
1655  proc->waitLock = NULL;
1656  proc->waitProcLock = NULL;
1657  proc->waitStatus = waitStatus;
1659 
1660  /* And awaken it */
1661  SetLatch(&proc->procLatch);
1662 }
static void dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node)
Definition: ilist.h:776

References Assert(), dclist_delete_from_thoroughly(), dlist_node_is_detached(), PGPROC::links, MyProc, pg_atomic_write_u64(), PROC_WAIT_STATUS_WAITING, PGPROC::procLatch, SetLatch(), PGPROC::waitLock, PGPROC::waitProcLock, LOCK::waitProcs, PGPROC::waitStart, and PGPROC::waitStatus.

Referenced by ProcLockWakeup().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 654 of file proc.c.

655 {
656  /* use volatile pointer to prevent code rearrangement */
657  volatile PROC_HDR *procglobal = ProcGlobal;
658 
659  procglobal->startupBufferPinWaitBufId = bufid;
660 }

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

Variable Documentation

◆ DeadlockTimeout

◆ IdleInTransactionSessionTimeout

PGDLLIMPORT int IdleInTransactionSessionTimeout
extern

Definition at line 61 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

PGDLLIMPORT int IdleSessionTimeout
extern

Definition at line 62 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

PGDLLIMPORT int LockTimeout
extern

Definition at line 60 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

PGDLLIMPORT bool log_lock_waits
extern

Definition at line 63 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGDLLIMPORT PGPROC* MyProc
extern

Definition at line 66 of file proc.c.

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

◆ PreparedXactProcs

PGDLLIMPORT PGPROC* PreparedXactProcs
extern

Definition at line 80 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ StatementTimeout

PGDLLIMPORT int StatementTimeout
extern

Definition at line 59 of file proc.c.

Referenced by enable_statement_timeout().