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)
 
void ProcReleaseLocks (bool isCommit)
 
void ProcQueueInit (PROC_QUEUE *queue)
 
ProcWaitStatus ProcSleep (LOCALLOCK *locallock, LockMethod lockMethodTable)
 
PGPROCProcWakeup (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 968 of file proc.c.

969 {
970  PGPROC *result = NULL;
971  int index;
972 
973  if (pid == 0) /* never match dummy PGPROCs */
974  return NULL;
975 
976  for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
977  {
978  PGPROC *proc = &AuxiliaryProcs[index];
979 
980  if (proc->pid == pid)
981  {
982  result = proc;
983  break;
984  }
985  }
986  return result;
987 }
#define NUM_AUXILIARY_PROCS
Definition: proc.h:418
NON_EXEC_STATIC PGPROC * AuxiliaryProcs
Definition: proc.c:81
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 1905 of file proc.c.

1906 {
1907  LWLock *leader_lwlock;
1908 
1909  /* If we already did it, we don't need to do it again. */
1910  if (MyProc->lockGroupLeader == MyProc)
1911  return;
1912 
1913  /* We had better not be a follower. */
1914  Assert(MyProc->lockGroupLeader == NULL);
1915 
1916  /* Create single-member group, containing only ourselves. */
1917  leader_lwlock = LockHashPartitionLockByProc(MyProc);
1918  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1921  LWLockRelease(leader_lwlock);
1922 }
static void dlist_push_head(dlist_head *head, dlist_node *node)
Definition: ilist.h:336
Assert(fmt[strlen(fmt) - 1] !='\n')
#define LockHashPartitionLockByProc(leader_pgproc)
Definition: lock.h:534
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1194
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1802
@ LW_EXCLUSIVE
Definition: lwlock.h:112
PGPROC * MyProc
Definition: proc.c:68
Definition: lwlock.h:40
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 1935 of file proc.c.

1936 {
1937  LWLock *leader_lwlock;
1938  bool ok = false;
1939 
1940  /* Group leader can't become member of group */
1941  Assert(MyProc != leader);
1942 
1943  /* Can't already be a member of a group */
1944  Assert(MyProc->lockGroupLeader == NULL);
1945 
1946  /* PID must be valid. */
1947  Assert(pid != 0);
1948 
1949  /*
1950  * Get lock protecting the group fields. Note LockHashPartitionLockByProc
1951  * accesses leader->pgprocno in a PGPROC that might be free. This is safe
1952  * because all PGPROCs' pgprocno fields are set during shared memory
1953  * initialization and never change thereafter; so we will acquire the
1954  * correct lock even if the leader PGPROC is in process of being recycled.
1955  */
1956  leader_lwlock = LockHashPartitionLockByProc(leader);
1957  LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
1958 
1959  /* Is this the leader we're looking for? */
1960  if (leader->pid == pid && leader->lockGroupLeader == leader)
1961  {
1962  /* OK, join the group */
1963  ok = true;
1964  MyProc->lockGroupLeader = leader;
1966  }
1967  LWLockRelease(leader_lwlock);
1968 
1969  return ok;
1970 }
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:353

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

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

References got_deadlock_timeout, MyLatch, and SetLatch().

Referenced by InitPostgres(), and RecoveryConflictInterrupt().

◆ GetStartupBufferPinWaitBufId()

int GetStartupBufferPinWaitBufId ( void  )

Definition at line 645 of file proc.c.

646 {
647  /* use volatile pointer to prevent code rearrangement */
648  volatile PROC_HDR *procglobal = ProcGlobal;
649 
650  return procglobal->startupBufferPinWaitBufId;
651 }
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: proc.h:360
int startupBufferPinWaitBufId
Definition: proc.h:400

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by HoldingBufferPinThatDelaysRecovery(), and RecoveryConflictInterrupt().

◆ HaveNFreeProcs()

bool HaveNFreeProcs ( int  n)

Definition at line 659 of file proc.c.

660 {
661  PGPROC *proc;
662 
664 
665  proc = ProcGlobal->freeProcs;
666 
667  while (n > 0 && proc != NULL)
668  {
669  proc = (PGPROC *) proc->links.next;
670  n--;
671  }
672 
674 
675  return (n <= 0);
676 }
#define SpinLockRelease(lock)
Definition: spin.h:64
#define SpinLockAcquire(lock)
Definition: spin.h:62
NON_EXEC_STATIC slock_t * ProcStructLock
Definition: proc.c:77
SHM_QUEUE links
Definition: proc.h:164
PGPROC * freeProcs
Definition: proc.h:382
struct SHM_QUEUE * next
Definition: shmem.h:31

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

Referenced by InitPostgres().

◆ InitAuxiliaryProcess()

void InitAuxiliaryProcess ( void  )

Definition at line 515 of file proc.c.

516 {
517  PGPROC *auxproc;
518  int proctype;
519 
520  /*
521  * ProcGlobal should be set up already (if we are a backend, we inherit
522  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
523  */
524  if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
525  elog(PANIC, "proc header uninitialized");
526 
527  if (MyProc != NULL)
528  elog(ERROR, "you already exist");
529 
530  /*
531  * We use the ProcStructLock to protect assignment and releasing of
532  * AuxiliaryProcs entries.
533  *
534  * While we are holding the ProcStructLock, also copy the current shared
535  * estimate of spins_per_delay to local storage.
536  */
538 
540 
541  /*
542  * Find a free auxproc ... *big* trouble if there isn't one ...
543  */
544  for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
545  {
546  auxproc = &AuxiliaryProcs[proctype];
547  if (auxproc->pid == 0)
548  break;
549  }
550  if (proctype >= NUM_AUXILIARY_PROCS)
551  {
553  elog(FATAL, "all AuxiliaryProcs are in use");
554  }
555 
556  /* Mark auxiliary proc as in use by me */
557  /* use volatile pointer to prevent code rearrangement */
558  ((volatile PGPROC *) auxproc)->pid = MyProcPid;
559 
560  MyProc = auxproc;
561 
563 
564  /*
565  * Initialize all fields of MyProc, except for those previously
566  * initialized by InitProcGlobal.
567  */
571  MyProc->fpVXIDLock = false;
580  MyProc->delayChkptFlags = 0;
581  MyProc->statusFlags = 0;
583  MyProc->lwWaitMode = 0;
584  MyProc->waitLock = NULL;
585  MyProc->waitProcLock = NULL;
587 #ifdef USE_ASSERT_CHECKING
588  {
589  int i;
590 
591  /* Last process should have released all locks. */
592  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
594  }
595 #endif
596 
597  /*
598  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
599  * on it. That allows us to repoint the process latch, which so far
600  * points to process local one, to the shared one.
601  */
604 
605  /* now that we have a proc, report wait events to shared memory */
607 
608  /* Check that group locking fields are in a proper initial state. */
609  Assert(MyProc->lockGroupLeader == NULL);
611 
612  /*
613  * We might be reusing a semaphore that belonged to a failed process. So
614  * be careful and reinitialize its value here. (This is not strictly
615  * necessary anymore, but seems like a good idea for cleanliness.)
616  */
618 
619  /*
620  * Arrange to clean up at process exit.
621  */
623 }
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:37
#define PANIC
Definition: elog.h:38
#define ERROR
Definition: elog.h:35
int MyProcPid
Definition: globals.c:44
bool IsBackgroundWorker
Definition: globals.c:115
static bool dlist_is_empty(dlist_head *head)
Definition: ilist.h:325
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:361
int i
Definition: isn.c:73
void OwnLatch(Latch *latch)
Definition: latch.c:422
#define InvalidLocalTransactionId
Definition: lock.h:70
@ LW_WS_NOT_WAITING
Definition: lwlock.h:29
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:95
void SwitchToSharedLatch(void)
Definition: miscinit.c:216
void PGSemaphoreReset(PGSemaphore sema)
Definition: posix_sema.c:295
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
#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
void SHMQueueElemInit(SHM_QUEUE *queue)
Definition: shmqueue.c:57
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
static void AuxiliaryProcKill(int code, Datum arg)
Definition: proc.c:924
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
Oid roleId
Definition: proc.h:199
ProcWaitStatus waitStatus
Definition: proc.h:168
Oid tempNamespaceId
Definition: proc.h:201
uint8 lwWaiting
Definition: proc.h:214
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:252
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:50

References Assert(), AuxiliaryProcKill(), AuxiliaryProcs, PGPROC::backendId, PGPROC::databaseId, PGPROC::delayChkptFlags, 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, 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(), SHMQueueElemInit(), SHMQueueEmpty(), 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 301 of file proc.c.

302 {
303  PGPROC *volatile *procgloballist;
304 
305  /*
306  * ProcGlobal should be set up already (if we are a backend, we inherit
307  * this by fork() or EXEC_BACKEND mechanism from the postmaster).
308  */
309  if (ProcGlobal == NULL)
310  elog(PANIC, "proc header uninitialized");
311 
312  if (MyProc != NULL)
313  elog(ERROR, "you already exist");
314 
315  /* Decide which list should supply our PGPROC. */
317  procgloballist = &ProcGlobal->autovacFreeProcs;
318  else if (IsBackgroundWorker)
319  procgloballist = &ProcGlobal->bgworkerFreeProcs;
320  else if (am_walsender)
321  procgloballist = &ProcGlobal->walsenderFreeProcs;
322  else
323  procgloballist = &ProcGlobal->freeProcs;
324 
325  /*
326  * Try to get a proc struct from the appropriate free list. If this
327  * fails, we must be out of PGPROC structures (not to mention semaphores).
328  *
329  * While we are holding the ProcStructLock, also copy the current shared
330  * estimate of spins_per_delay to local storage.
331  */
333 
335 
336  MyProc = *procgloballist;
337 
338  if (MyProc != NULL)
339  {
340  *procgloballist = (PGPROC *) MyProc->links.next;
342  }
343  else
344  {
345  /*
346  * If we reach here, all the PGPROCs are in use. This is one of the
347  * possible places to detect "too many backends", so give the standard
348  * error message. XXX do we need to give a different failure message
349  * in the autovacuum case?
350  */
352  if (am_walsender)
353  ereport(FATAL,
354  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
355  errmsg("number of requested standby connections exceeds max_wal_senders (currently %d)",
356  max_wal_senders)));
357  ereport(FATAL,
358  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
359  errmsg("sorry, too many clients already")));
360  }
361 
362  /*
363  * Cross-check that the PGPROC is of the type we expect; if this were not
364  * the case, it would get returned to the wrong list.
365  */
366  Assert(MyProc->procgloballist == procgloballist);
367 
368  /*
369  * Now that we have a PGPROC, mark ourselves as an active postmaster
370  * child; this is so that the postmaster can detect it if we exit without
371  * cleaning up. (XXX autovac launcher currently doesn't participate in
372  * this; it probably should.)
373  */
376 
377  /*
378  * Initialize all fields of MyProc, except for those previously
379  * initialized by InitProcGlobal.
380  */
384  MyProc->fpVXIDLock = false;
388  MyProc->pid = MyProcPid;
389  /* backendId, databaseId and roleId will be filled in later */
395  MyProc->delayChkptFlags = 0;
396  MyProc->statusFlags = 0;
397  /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
401  MyProc->lwWaitMode = 0;
402  MyProc->waitLock = NULL;
403  MyProc->waitProcLock = NULL;
405 #ifdef USE_ASSERT_CHECKING
406  {
407  int i;
408 
409  /* Last process should have released all locks. */
410  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
412  }
413 #endif
415 
416  /* Initialize fields for sync rep */
417  MyProc->waitLSN = 0;
420 
421  /* Initialize fields for group XID clearing. */
422  MyProc->procArrayGroupMember = false;
425 
426  /* Check that group locking fields are in a proper initial state. */
427  Assert(MyProc->lockGroupLeader == NULL);
429 
430  /* Initialize wait event information. */
431  MyProc->wait_event_info = 0;
432 
433  /* Initialize fields for group transaction status update. */
434  MyProc->clogGroupMember = false;
440 
441  /*
442  * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
443  * on it. That allows us to repoint the process latch, which so far
444  * points to process local one, to the shared one.
445  */
448 
449  /* now that we have a proc, report wait events to shared memory */
451 
452  /*
453  * We might be reusing a semaphore that belonged to a failed process. So
454  * be careful and reinitialize its value here. (This is not strictly
455  * necessary anymore, but seems like a good idea for cleanliness.)
456  */
458 
459  /*
460  * Arrange to clean up at backend exit.
461  */
463 
464  /*
465  * Now that we have a PGPROC, we could try to acquire locks, so initialize
466  * local state needed for LWLocks, and the deadlock checker.
467  */
470 }
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:236
bool IsAutoVacuumLauncherProcess(void)
Definition: autovacuum.c:3308
bool IsAutoVacuumWorkerProcess(void)
Definition: autovacuum.c:3314
#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:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ereport(elevel,...)
Definition: elog.h:145
bool IsUnderPostmaster
Definition: globals.c:113
void InitLWLockAccess(void)
Definition: lwlock.c:580
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:803
PGPROC ** procgloballist
Definition: proc.h:165
bool procArrayGroupMember
Definition: proc.h:260
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:280
pg_atomic_uint32 procArrayGroupNext
Definition: proc.h:262
int clogGroupMemberPage
Definition: proc.h:278
bool recoveryConflictPending
Definition: proc.h:211
TransactionId clogGroupMemberXid
Definition: proc.h:275
bool clogGroupMember
Definition: proc.h:273
XLogRecPtr waitLSN
Definition: proc.h:243
int syncRepState
Definition: proc.h:244
pg_atomic_uint32 clogGroupNext
Definition: proc.h:274
SHM_QUEUE syncRepLinks
Definition: proc.h:245
XidStatus clogGroupMemberXidStatus
Definition: proc.h:276
TransactionId procArrayGroupMemberXid
Definition: proc.h:268
PGPROC * walsenderFreeProcs
Definition: proc.h:388
PGPROC * autovacFreeProcs
Definition: proc.h:384
PGPROC * 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(), 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, SHM_QUEUE::next, 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(), SHMQueueElemInit(), SHMQueueEmpty(), 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(), BackendStartup(), BootstrapModeMain(), PostgresSingleUserMain(), and StartBackgroundWorker().

◆ InitProcessPhase2()

void InitProcessPhase2 ( void  )

Definition at line 480 of file proc.c.

481 {
482  Assert(MyProc != NULL);
483 
484  /*
485  * Add our PGPROC to the PGPROC array in shared memory.
486  */
488 
489  /*
490  * Arrange to clean that up at backend exit.
491  */
493 }
void ProcArrayAdd(PGPROC *proc)
Definition: procarray.c:472
static void RemoveProcFromArray(int code, Datum arg)
Definition: proc.c:792

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

Referenced by InitPostgres().

◆ InitProcGlobal()

void InitProcGlobal ( void  )

Definition at line 159 of file proc.c.

160 {
161  PGPROC *procs;
162  int i,
163  j;
164  bool found;
166 
167  /* Create the ProcGlobal shared structure */
168  ProcGlobal = (PROC_HDR *)
169  ShmemInitStruct("Proc Header", sizeof(PROC_HDR), &found);
170  Assert(!found);
171 
172  /*
173  * Initialize the data structures.
174  */
176  ProcGlobal->freeProcs = NULL;
181  ProcGlobal->walwriterLatch = NULL;
185 
186  /*
187  * Create and initialize all the PGPROC structures we'll need. There are
188  * five separate consumers: (1) normal backends, (2) autovacuum workers
189  * and the autovacuum launcher, (3) background workers, (4) auxiliary
190  * processes, and (5) prepared transactions. Each PGPROC structure is
191  * dedicated to exactly one of these purposes, and they do not move
192  * between groups.
193  */
194  procs = (PGPROC *) ShmemAlloc(TotalProcs * sizeof(PGPROC));
195  MemSet(procs, 0, TotalProcs * sizeof(PGPROC));
196  ProcGlobal->allProcs = procs;
197  /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
199 
200  /*
201  * Allocate arrays mirroring PGPROC fields in a dense manner. See
202  * PROC_HDR.
203  *
204  * XXX: It might make sense to increase padding for these arrays, given
205  * how hotly they are accessed.
206  */
207  ProcGlobal->xids =
208  (TransactionId *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->xids));
209  MemSet(ProcGlobal->xids, 0, TotalProcs * sizeof(*ProcGlobal->xids));
211  MemSet(ProcGlobal->subxidStates, 0, TotalProcs * sizeof(*ProcGlobal->subxidStates));
212  ProcGlobal->statusFlags = (uint8 *) ShmemAlloc(TotalProcs * sizeof(*ProcGlobal->statusFlags));
213  MemSet(ProcGlobal->statusFlags, 0, TotalProcs * sizeof(*ProcGlobal->statusFlags));
214 
215  for (i = 0; i < TotalProcs; 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  procs[i].sem = PGSemaphoreCreate();
227  InitSharedLatch(&(procs[i].procLatch));
228  LWLockInitialize(&(procs[i].fpInfoLock), LWTRANCHE_LOCK_FASTPATH);
229  }
230  procs[i].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 */
243  procs[i].links.next = (SHM_QUEUE *) ProcGlobal->freeProcs;
244  ProcGlobal->freeProcs = &procs[i];
246  }
247  else if (i < MaxConnections + autovacuum_max_workers + 1)
248  {
249  /* PGPROC for AV launcher/worker, add to autovacFreeProcs list */
251  ProcGlobal->autovacFreeProcs = &procs[i];
253  }
255  {
256  /* PGPROC for bgworker, add to bgworkerFreeProcs list */
258  ProcGlobal->bgworkerFreeProcs = &procs[i];
260  }
261  else if (i < MaxBackends)
262  {
263  /* PGPROC for walsender, add to walsenderFreeProcs list */
265  ProcGlobal->walsenderFreeProcs = &procs[i];
267  }
268 
269  /* Initialize myProcLocks[] shared memory queues. */
270  for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
271  SHMQueueInit(&(procs[i].myProcLocks[j]));
272 
273  /* Initialize lockGroupMembers list. */
274  dlist_init(&procs[i].lockGroupMembers);
275 
276  /*
277  * Initialize the atomic variables, otherwise, it won't be safe to
278  * access them for backends that aren't currently in use.
279  */
280  pg_atomic_init_u32(&(procs[i].procArrayGroupNext), INVALID_PGPROCNO);
281  pg_atomic_init_u32(&(procs[i].clogGroupNext), INVALID_PGPROCNO);
282  pg_atomic_init_u64(&(procs[i].waitStart), 0);
283  }
284 
285  /*
286  * Save pointers to the blocks of PGPROC structures reserved for auxiliary
287  * processes and prepared transactions.
288  */
289  AuxiliaryProcs = &procs[MaxBackends];
291 
292  /* Create ProcStructLock spinlock, too */
293  ProcStructLock = (slock_t *) ShmemAlloc(sizeof(slock_t));
295 }
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:442
unsigned char uint8
Definition: c.h:440
#define MemSet(start, val, len)
Definition: c.h:953
uint32 TransactionId
Definition: c.h:588
int MaxConnections
Definition: globals.c:137
int MaxBackends
Definition: globals.c:140
int max_worker_processes
Definition: globals.c:138
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
int j
Definition: isn.c:74
void InitSharedLatch(Latch *latch)
Definition: latch.c:389
void LWLockInitialize(LWLock *lock, int tranche_id)
Definition: lwlock.c:729
@ LWTRANCHE_LOCK_FASTPATH
Definition: lwlock.h:188
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
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
#define SpinLockInit(lock)
Definition: spin.h:60
PGPROC * PreparedXactProcs
Definition: proc.c:82
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:117

References 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, j, PGPROC::links, LWLockInitialize(), LWTRANCHE_LOCK_FASTPATH, max_prepared_xacts, max_worker_processes, MaxBackends, MaxConnections, MemSet, SHM_QUEUE::next, NUM_AUXILIARY_PROCS, NUM_LOCK_PARTITIONS, pg_atomic_init_u32(), pg_atomic_init_u64(), PGPROC::pgprocno, PGSemaphoreCreate(), PreparedXactProcs, PROC_HDR::procArrayGroupFirst, ProcGlobal, PGPROC::procgloballist, ProcStructLock, PGPROC::sem, ShmemAlloc(), ShmemInitStruct(), SHMQueueInit(), SpinLockInit, PROC_HDR::spins_per_delay, PROC_HDR::startupBufferPinWaitBufId, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PROC_HDR::walsenderFreeProcs, PROC_HDR::walwriterLatch, and PROC_HDR::xids.

Referenced by CreateSharedMemoryAndSemaphores().

◆ IsWaitingForLock()

bool IsWaitingForLock ( void  )

Definition at line 682 of file proc.c.

683 {
684  if (lockAwaited == NULL)
685  return false;
686 
687  return true;
688 }
static LOCALLOCK * lockAwaited
Definition: proc.c:85

References lockAwaited.

Referenced by RecoveryConflictInterrupt().

◆ LockErrorCleanup()

void LockErrorCleanup ( void  )

Definition at line 699 of file proc.c.

700 {
701  LWLock *partitionLock;
702  DisableTimeoutParams timeouts[2];
703 
704  HOLD_INTERRUPTS();
705 
707 
708  /* Nothing to do if we weren't waiting for a lock */
709  if (lockAwaited == NULL)
710  {
712  return;
713  }
714 
715  /*
716  * Turn off the deadlock and lock timeout timers, if they are still
717  * running (see ProcSleep). Note we must preserve the LOCK_TIMEOUT
718  * indicator flag, since this function is executed before
719  * ProcessInterrupts when responding to SIGINT; else we'd lose the
720  * knowledge that the SIGINT came from a lock timeout and not an external
721  * source.
722  */
723  timeouts[0].id = DEADLOCK_TIMEOUT;
724  timeouts[0].keep_indicator = false;
725  timeouts[1].id = LOCK_TIMEOUT;
726  timeouts[1].keep_indicator = true;
727  disable_timeouts(timeouts, 2);
728 
729  /* Unlink myself from the wait queue, if on it (might not be anymore!) */
730  partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
731  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
732 
733  if (MyProc->links.next != NULL)
734  {
735  /* We could not have been granted the lock yet */
737  }
738  else
739  {
740  /*
741  * Somebody kicked us off the lock queue already. Perhaps they
742  * granted us the lock, or perhaps they detected a deadlock. If they
743  * did grant us the lock, we'd better remember it in our local lock
744  * table.
745  */
748  }
749 
750  lockAwaited = NULL;
751 
752  LWLockRelease(partitionLock);
753 
755 }
void GrantAwaitedLock(void)
Definition: lock.c:1786
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition: lock.c:1918
void AbortStrongLockAcquire(void)
Definition: lock.c:1757
#define LockHashPartitionLock(hashcode)
Definition: lock.h:519
#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:424
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(), GrantAwaitedLock(), LOCALLOCK::hashcode, HOLD_INTERRUPTS, DisableTimeoutParams::id, DisableTimeoutParams::keep_indicator, PGPROC::links, LOCK_TIMEOUT, lockAwaited, LockHashPartitionLock, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, SHM_QUEUE::next, PROC_WAIT_STATUS_OK, RemoveFromWaitQueue(), RESUME_INTERRUPTS, and PGPROC::waitStatus.

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

◆ ProcGlobalSemas()

int ProcGlobalSemas ( void  )

Definition at line 124 of file proc.c.

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

References MaxBackends, and NUM_AUXILIARY_PROCS.

Referenced by CalculateShmemSize().

◆ ProcGlobalShmemSize()

Size ProcGlobalShmemSize ( void  )

Definition at line 102 of file proc.c.

103 {
104  Size size = 0;
105  Size TotalProcs =
107 
108  /* ProcGlobal */
109  size = add_size(size, sizeof(PROC_HDR));
110  size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
111  size = add_size(size, sizeof(slock_t));
112 
113  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
114  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
115  size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
116 
117  return size;
118 }
size_t Size
Definition: c.h:541
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 1707 of file proc.c.

1708 {
1709  PROC_QUEUE *waitQueue = &(lock->waitProcs);
1710  int queue_size = waitQueue->size;
1711  PGPROC *proc;
1712  LOCKMASK aheadRequests = 0;
1713 
1714  Assert(queue_size >= 0);
1715 
1716  if (queue_size == 0)
1717  return;
1718 
1719  proc = (PGPROC *) waitQueue->links.next;
1720 
1721  while (queue_size-- > 0)
1722  {
1723  LOCKMODE lockmode = proc->waitLockMode;
1724 
1725  /*
1726  * Waken if (a) doesn't conflict with requests of earlier waiters, and
1727  * (b) doesn't conflict with already-held locks.
1728  */
1729  if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
1730  !LockCheckConflicts(lockMethodTable, lockmode, lock,
1731  proc->waitProcLock))
1732  {
1733  /* OK to waken */
1734  GrantLock(lock, proc->waitProcLock, lockmode);
1735  proc = ProcWakeup(proc, PROC_WAIT_STATUS_OK);
1736 
1737  /*
1738  * ProcWakeup removes proc from the lock's waiting process queue
1739  * and returns the next proc in chain; don't use proc's next-link,
1740  * because it's been cleared.
1741  */
1742  }
1743  else
1744  {
1745  /*
1746  * Cannot wake this guy. Remember his request for later checks.
1747  */
1748  aheadRequests |= LOCKBIT_ON(lockmode);
1749  proc = (PGPROC *) proc->links.next;
1750  }
1751  }
1752 
1753  Assert(waitQueue->size >= 0);
1754 }
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1555
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1420
#define LOCKBIT_ON(lockmode)
Definition: lock.h:89
int LOCKMODE
Definition: lockdefs.h:26
int LOCKMASK
Definition: lockdefs.h:25
while(p+4<=pend)
PGPROC * ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
Definition: proc.c:1670
PROC_QUEUE waitProcs
Definition: lock.h:309
const LOCKMASK * conflictTab
Definition: lock.h:116
LOCKMODE waitLockMode
Definition: proc.h:225
SHM_QUEUE links
Definition: lock.h:32
int size
Definition: lock.h:33

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

Referenced by CleanUpLock(), and DeadLockCheck().

◆ ProcQueueInit()

void ProcQueueInit ( PROC_QUEUE queue)

Definition at line 1021 of file proc.c.

1022 {
1023  SHMQueueInit(&(queue->links));
1024  queue->size = 0;
1025 }

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

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

◆ ProcReleaseLocks()

void ProcReleaseLocks ( bool  isCommit)

Definition at line 775 of file proc.c.

776 {
777  if (!MyProc)
778  return;
779  /* If waiting, get off wait queue (should only be needed after error) */
781  /* Release standard locks, including session-level if aborting */
783  /* Release transaction-level advisory locks */
785 }
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition: lock.c:2180
#define DEFAULT_LOCKMETHOD
Definition: lock.h:130
#define USER_LOCKMETHOD
Definition: lock.h:131
void LockErrorCleanup(void)
Definition: proc.c:699

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

Referenced by ResourceOwnerReleaseInternal().

◆ ProcSendSignal()

void ProcSendSignal ( int  pgprocno)

Definition at line 1890 of file proc.c.

1891 {
1892  if (pgprocno < 0 || pgprocno >= ProcGlobal->allProcCount)
1893  elog(ERROR, "pgprocno out of range");
1894 
1895  SetLatch(&ProcGlobal->allProcs[pgprocno].procLatch);
1896 }

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

Referenced by ReleasePredicateLocks(), and UnpinBuffer().

◆ ProcSleep()

ProcWaitStatus ProcSleep ( LOCALLOCK locallock,
LockMethod  lockMethodTable 
)

Definition at line 1045 of file proc.c.

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

References AccessExclusiveLock, 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(), errmsg_internal(), get_timeout_start_time(), GetBlockingAutoVacuumPgproc(), GetCurrentTimestamp(), GetLockConflicts(), 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, lockAwaited, LOCKBIT_ON, LockCheckConflicts(), PGPROC::lockGroupLeader, LockHashPartitionLock, PROCLOCK::lockLink, 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, SHM_QUEUE::next, 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(), SHMQueueInsertBefore(), SHMQueueNext(), PROC_QUEUE::size, 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()

PGPROC* ProcWakeup ( PGPROC proc,
ProcWaitStatus  waitStatus 
)

Definition at line 1670 of file proc.c.

1671 {
1672  PGPROC *retProc;
1673 
1674  /* Proc should be sleeping ... */
1675  if (proc->links.prev == NULL ||
1676  proc->links.next == NULL)
1677  return NULL;
1679 
1680  /* Save next process before we zap the list link */
1681  retProc = (PGPROC *) proc->links.next;
1682 
1683  /* Remove process from wait queue */
1684  SHMQueueDelete(&(proc->links));
1685  (proc->waitLock->waitProcs.size)--;
1686 
1687  /* Clean up process' state and pass it the ok/fail signal */
1688  proc->waitLock = NULL;
1689  proc->waitProcLock = NULL;
1690  proc->waitStatus = waitStatus;
1692 
1693  /* And awaken it */
1694  SetLatch(&proc->procLatch);
1695 
1696  return retProc;
1697 }
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
struct SHM_QUEUE * prev
Definition: shmem.h:30

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

Referenced by ProcLockWakeup().

◆ SetStartupBufferPinWaitBufId()

void SetStartupBufferPinWaitBufId ( int  bufid)

Definition at line 633 of file proc.c.

634 {
635  /* use volatile pointer to prevent code rearrangement */
636  volatile PROC_HDR *procglobal = ProcGlobal;
637 
638  procglobal->startupBufferPinWaitBufId = bufid;
639 }

References ProcGlobal, and PROC_HDR::startupBufferPinWaitBufId.

Referenced by LockBufferForCleanup().

Variable Documentation

◆ DeadlockTimeout

◆ IdleInTransactionSessionTimeout

PGDLLIMPORT int IdleInTransactionSessionTimeout
extern

Definition at line 63 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ IdleSessionTimeout

PGDLLIMPORT int IdleSessionTimeout
extern

Definition at line 64 of file proc.c.

Referenced by PostgresMain(), and ProcessInterrupts().

◆ LockTimeout

PGDLLIMPORT int LockTimeout
extern

Definition at line 62 of file proc.c.

Referenced by ProcSleep().

◆ log_lock_waits

PGDLLIMPORT bool log_lock_waits
extern

Definition at line 65 of file proc.c.

Referenced by ProcSleep().

◆ MyProc

PGDLLIMPORT PGPROC* MyProc
extern

Definition at line 68 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(), 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(), parallel_vacuum_main(), ParallelWorkerMain(), PgArchiverMain(), pgstat_report_activity(), PhysicalReplicationSlotNewXmin(), PostPrepare_Locks(), PrepareTransaction(), ProcArrayGroupClearXid(), ProcArrayInstallImportedXmin(), ProcArrayInstallRestoredXmin(), ProcessStandbyHSFeedbackMessage(), ProcKill(), ProcReleaseLocks(), ProcSleep(), ProcWakeup(), RecordTransactionCommit(), RecordTransactionCommitPrepared(), RecoveryConflictInterrupt(), 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(), TransactionIdLimitedForOldSnapshots(), 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 82 of file proc.c.

Referenced by InitProcGlobal(), and TwoPhaseShmemInit().

◆ ProcGlobal

◆ StatementTimeout

PGDLLIMPORT int StatementTimeout
extern

Definition at line 61 of file proc.c.

Referenced by enable_statement_timeout().