PostgreSQL Source Code  git master
lock.h File Reference
#include "storage/lockdefs.h"
#include "storage/backendid.h"
#include "storage/lwlock.h"
#include "storage/shmem.h"
Include dependency graph for lock.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PROC_QUEUE
 
struct  VirtualTransactionId
 
struct  LockMethodData
 
struct  LOCKTAG
 
struct  LOCK
 
struct  PROCLOCKTAG
 
struct  PROCLOCK
 
struct  LOCALLOCKTAG
 
struct  LOCALLOCKOWNER
 
struct  LOCALLOCK
 
struct  LockInstanceData
 
struct  LockData
 
struct  BlockedProcData
 
struct  BlockedProcsData
 

Macros

#define InvalidLocalTransactionId   0
 
#define LocalTransactionIdIsValid(lxid)   ((lxid) != InvalidLocalTransactionId)
 
#define VirtualTransactionIdIsValid(vxid)
 
#define VirtualTransactionIdEquals(vxid1, vxid2)
 
#define SetInvalidVirtualTransactionId(vxid)
 
#define GET_VXID_FROM_PGPROC(vxid, proc)
 
#define MAX_LOCKMODES   10
 
#define LOCKBIT_ON(lockmode)   (1 << (lockmode))
 
#define LOCKBIT_OFF(lockmode)   (~(1 << (lockmode)))
 
#define DEFAULT_LOCKMETHOD   1
 
#define USER_LOCKMETHOD   2
 
#define LOCKTAG_LAST_TYPE   LOCKTAG_ADVISORY
 
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
 
#define SET_LOCKTAG_RELATION_EXTEND(locktag, dboid, reloid)
 
#define SET_LOCKTAG_PAGE(locktag, dboid, reloid, blocknum)
 
#define SET_LOCKTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
 
#define SET_LOCKTAG_TRANSACTION(locktag, xid)
 
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
 
#define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag, xid, token)
 
#define SET_LOCKTAG_OBJECT(locktag, dboid, classoid, objoid, objsubid)
 
#define SET_LOCKTAG_ADVISORY(locktag, id1, id2, id3, id4)
 
#define LOCK_LOCKMETHOD(lock)   ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
 
#define PROCLOCK_LOCKMETHOD(proclock)   LOCK_LOCKMETHOD(*((proclock).tag.myLock))
 
#define LOCALLOCK_LOCKMETHOD(llock)   ((llock).tag.lock.locktag_lockmethodid)
 
#define LockHashPartition(hashcode)   ((hashcode) % NUM_LOCK_PARTITIONS)
 
#define LockHashPartitionLock(hashcode)
 
#define LockHashPartitionLockByIndex(i)   (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
 
#define LockHashPartitionLockByProc(leader_pgproc)   LockHashPartitionLock((leader_pgproc)->pgprocno)
 

Typedefs

typedef struct PGPROC PGPROC
 
typedef struct PROC_QUEUE PROC_QUEUE
 
typedef struct LockMethodData LockMethodData
 
typedef const LockMethodDataLockMethod
 
typedef uint16 LOCKMETHODID
 
typedef enum LockTagType LockTagType
 
typedef struct LOCKTAG LOCKTAG
 
typedef struct LOCK LOCK
 
typedef struct PROCLOCKTAG PROCLOCKTAG
 
typedef struct PROCLOCK PROCLOCK
 
typedef struct LOCALLOCKTAG LOCALLOCKTAG
 
typedef struct LOCALLOCKOWNER LOCALLOCKOWNER
 
typedef struct LOCALLOCK LOCALLOCK
 
typedef struct LockInstanceData LockInstanceData
 
typedef struct LockData LockData
 
typedef struct BlockedProcData BlockedProcData
 
typedef struct BlockedProcsData BlockedProcsData
 

Enumerations

enum  LockTagType {
  LOCKTAG_RELATION, LOCKTAG_RELATION_EXTEND, LOCKTAG_PAGE, LOCKTAG_TUPLE,
  LOCKTAG_TRANSACTION, LOCKTAG_VIRTUALTRANSACTION, LOCKTAG_SPECULATIVE_TOKEN, LOCKTAG_OBJECT,
  LOCKTAG_USERLOCK, LOCKTAG_ADVISORY
}
 
enum  LockAcquireResult { LOCKACQUIRE_NOT_AVAIL, LOCKACQUIRE_OK, LOCKACQUIRE_ALREADY_HELD, LOCKACQUIRE_ALREADY_CLEAR }
 
enum  DeadLockState {
  DS_NOT_YET_CHECKED, DS_NO_DEADLOCK, DS_SOFT_DEADLOCK, DS_HARD_DEADLOCK,
  DS_BLOCKED_BY_AUTOVACUUM
}
 

Functions

void InitLocks (void)
 
LockMethod GetLocksMethodTable (const LOCK *lock)
 
LockMethod GetLockTagsMethodTable (const LOCKTAG *locktag)
 
uint32 LockTagHashCode (const LOCKTAG *locktag)
 
bool DoLockModesConflict (LOCKMODE mode1, LOCKMODE mode2)
 
LockAcquireResult LockAcquire (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
 
LockAcquireResult LockAcquireExtended (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp)
 
void AbortStrongLockAcquire (void)
 
void MarkLockClear (LOCALLOCK *locallock)
 
bool LockRelease (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
void LockReleaseAll (LOCKMETHODID lockmethodid, bool allLocks)
 
void LockReleaseSession (LOCKMETHODID lockmethodid)
 
void LockReleaseCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
void LockReassignCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
bool LockHasWaiters (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
VirtualTransactionIdGetLockConflicts (const LOCKTAG *locktag, LOCKMODE lockmode)
 
void AtPrepare_Locks (void)
 
void PostPrepare_Locks (TransactionId xid)
 
int LockCheckConflicts (LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
 
void GrantLock (LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
 
void GrantAwaitedLock (void)
 
void RemoveFromWaitQueue (PGPROC *proc, uint32 hashcode)
 
Size LockShmemSize (void)
 
LockDataGetLockStatusData (void)
 
BlockedProcsDataGetBlockerStatusData (int blocked_pid)
 
xl_standby_lockGetRunningTransactionLocks (int *nlocks)
 
const char * GetLockmodeName (LOCKMETHODID lockmethodid, LOCKMODE mode)
 
void lock_twophase_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_postcommit (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_postabort (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_standby_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
DeadLockState DeadLockCheck (PGPROC *proc)
 
PGPROCGetBlockingAutoVacuumPgproc (void)
 
void DeadLockReport (void) pg_attribute_noreturn()
 
void RememberSimpleDeadLock (PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
 
void InitDeadLockChecking (void)
 
int LockWaiterCount (const LOCKTAG *locktag)
 
void VirtualXactLockTableInsert (VirtualTransactionId vxid)
 
void VirtualXactLockTableCleanup (void)
 
bool VirtualXactLock (VirtualTransactionId vxid, bool wait)
 

Variables

int max_locks_per_xact
 
const char *const LockTagTypeNames []
 

Macro Definition Documentation

◆ DEFAULT_LOCKMETHOD

#define DEFAULT_LOCKMETHOD   1

◆ GET_VXID_FROM_PGPROC

#define GET_VXID_FROM_PGPROC (   vxid,
  proc 
)
Value:
((vxid).backendId = (proc).backendId, \
(vxid).localTransactionId = (proc).lxid)

Definition at line 80 of file lock.h.

Referenced by CancelDBBackends(), CancelVirtualTransaction(), GetConflictingVirtualXIDs(), GetCurrentVirtualXIDs(), GetLockConflicts(), GetSerializableTransactionSnapshotInt(), GetVirtualXIDsDelayingChkpt(), and HaveVirtualXIDsDelayingChkpt().

◆ InvalidLocalTransactionId

◆ LOCALLOCK_LOCKMETHOD

#define LOCALLOCK_LOCKMETHOD (   llock)    ((llock).tag.lock.locktag_lockmethodid)

Definition at line 418 of file lock.h.

Referenced by LockReleaseAll(), LockReleaseSession(), and WaitOnLock().

◆ LocalTransactionIdIsValid

#define LocalTransactionIdIsValid (   lxid)    ((lxid) != InvalidLocalTransactionId)

Definition at line 70 of file lock.h.

Referenced by GetNextLocalTransactionId(), and VirtualXactLockTableCleanup().

◆ LOCK_LOCKMETHOD

#define LOCK_LOCKMETHOD (   lock)    ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)

Definition at line 300 of file lock.h.

Referenced by GetLocksMethodTable(), LockReleaseAll(), and RemoveFromWaitQueue().

◆ LOCKBIT_OFF

#define LOCKBIT_OFF (   lockmode)    (~(1 << (lockmode)))

Definition at line 88 of file lock.h.

Referenced by GrantLock(), pg_lock_status(), RemoveFromWaitQueue(), and UnGrantLock().

◆ LOCKBIT_ON

◆ LockHashPartition

#define LockHashPartition (   hashcode)    ((hashcode) % NUM_LOCK_PARTITIONS)

Definition at line 497 of file lock.h.

Referenced by lock_twophase_recover(), and SetupLockInTable().

◆ LockHashPartitionLock

#define LockHashPartitionLock (   hashcode)

◆ LockHashPartitionLockByIndex

#define LockHashPartitionLockByIndex (   i)    (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)

◆ LockHashPartitionLockByProc

#define LockHashPartitionLockByProc (   leader_pgproc)    LockHashPartitionLock((leader_pgproc)->pgprocno)

Definition at line 514 of file lock.h.

Referenced by BecomeLockGroupLeader(), BecomeLockGroupMember(), and ProcKill().

◆ LOCKTAG_LAST_TYPE

#define LOCKTAG_LAST_TYPE   LOCKTAG_ADVISORY

Definition at line 166 of file lock.h.

Referenced by GetLockNameFromTagType(), and pg_lock_status().

◆ MAX_LOCKMODES

◆ PROCLOCK_LOCKMETHOD

#define PROCLOCK_LOCKMETHOD (   proclock)    LOCK_LOCKMETHOD(*((proclock).tag.myLock))

Definition at line 357 of file lock.h.

◆ SET_LOCKTAG_ADVISORY

#define SET_LOCKTAG_ADVISORY (   locktag,
  id1,
  id2,
  id3,
  id4 
)
Value:
((locktag).locktag_field1 = (id1), \
(locktag).locktag_field2 = (id2), \
(locktag).locktag_field3 = (id3), \
(locktag).locktag_field4 = (id4), \
(locktag).locktag_type = LOCKTAG_ADVISORY, \
(locktag).locktag_lockmethodid = USER_LOCKMETHOD)
#define USER_LOCKMETHOD
Definition: lock.h:129

Definition at line 257 of file lock.h.

◆ SET_LOCKTAG_OBJECT

#define SET_LOCKTAG_OBJECT (   locktag,
  dboid,
  classoid,
  objoid,
  objsubid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (classoid), \
(locktag).locktag_field3 = (objoid), \
(locktag).locktag_field4 = (objsubid), \
(locktag).locktag_type = LOCKTAG_OBJECT, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
Oid classoid
Definition: pg_shseclabel.h:31

Definition at line 249 of file lock.h.

Referenced by LockDatabaseObject(), LockSharedObject(), LockSharedObjectForSession(), UnlockDatabaseObject(), UnlockSharedObject(), and UnlockSharedObjectForSession().

◆ SET_LOCKTAG_PAGE

#define SET_LOCKTAG_PAGE (   locktag,
  dboid,
  reloid,
  blocknum 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = (blocknum), \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_PAGE, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 209 of file lock.h.

Referenced by ConditionalLockPage(), LockPage(), and UnlockPage().

◆ SET_LOCKTAG_RELATION

#define SET_LOCKTAG_RELATION (   locktag,
  dboid,
  reloid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_RELATION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 193 of file lock.h.

Referenced by ConditionalLockRelation(), DefineIndex(), GetLockStatusData(), index_drop(), LockHasWaitersRelation(), LockRelation(), LockRelationIdForSession(), SetLocktagRelationOid(), StandbyAcquireAccessExclusiveLock(), StandbyReleaseLockList(), UnlockRelation(), UnlockRelationId(), and UnlockRelationIdForSession().

◆ SET_LOCKTAG_RELATION_EXTEND

#define SET_LOCKTAG_RELATION_EXTEND (   locktag,
  dboid,
  reloid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 201 of file lock.h.

Referenced by ConditionalLockRelationForExtension(), LockRelationForExtension(), RelationExtensionLockWaiterCount(), and UnlockRelationForExtension().

◆ SET_LOCKTAG_SPECULATIVE_INSERTION

#define SET_LOCKTAG_SPECULATIVE_INSERTION (   locktag,
  xid,
  token 
)
Value:
((locktag).locktag_field1 = (xid), \
(locktag).locktag_field2 = (token), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_SPECULATIVE_TOKEN, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 241 of file lock.h.

Referenced by SpeculativeInsertionLockAcquire(), SpeculativeInsertionLockRelease(), and SpeculativeInsertionWait().

◆ SET_LOCKTAG_TRANSACTION

#define SET_LOCKTAG_TRANSACTION (   locktag,
  xid 
)
Value:
((locktag).locktag_field1 = (xid), \
(locktag).locktag_field2 = 0, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_TRANSACTION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 225 of file lock.h.

Referenced by ConditionalXactLockTableWait(), XactLockTableDelete(), XactLockTableInsert(), and XactLockTableWait().

◆ SET_LOCKTAG_TUPLE

#define SET_LOCKTAG_TUPLE (   locktag,
  dboid,
  reloid,
  blocknum,
  offnum 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = (blocknum), \
(locktag).locktag_field4 = (offnum), \
(locktag).locktag_type = LOCKTAG_TUPLE, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 217 of file lock.h.

Referenced by ConditionalLockTuple(), LockTuple(), and UnlockTuple().

◆ SET_LOCKTAG_VIRTUALTRANSACTION

#define SET_LOCKTAG_VIRTUALTRANSACTION (   locktag,
  vxid 
)
Value:
((locktag).locktag_field1 = (vxid).backendId, \
(locktag).locktag_field2 = (vxid).localTransactionId, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128

Definition at line 233 of file lock.h.

Referenced by GetLockStatusData(), VirtualXactLock(), and VirtualXactLockTableCleanup().

◆ SetInvalidVirtualTransactionId

#define SetInvalidVirtualTransactionId (   vxid)
Value:
((vxid).backendId = InvalidBackendId, \
(vxid).localTransactionId = InvalidLocalTransactionId)
#define InvalidBackendId
Definition: backendid.h:23
#define InvalidLocalTransactionId
Definition: lock.h:69

Definition at line 77 of file lock.h.

Referenced by DefineIndex(), and InitPredicateLocks().

◆ USER_LOCKMETHOD

#define USER_LOCKMETHOD   2

Definition at line 129 of file lock.h.

Referenced by DiscardAll(), pg_advisory_unlock_all(), ProcReleaseLocks(), and ShutdownPostgres().

◆ VirtualTransactionIdEquals

#define VirtualTransactionIdEquals (   vxid1,
  vxid2 
)
Value:
((vxid1).backendId == (vxid2).backendId && \
(vxid1).localTransactionId == (vxid2).localTransactionId)

Definition at line 74 of file lock.h.

Referenced by DefineIndex(), GetLockConflicts(), and HaveVirtualXIDsDelayingChkpt().

◆ VirtualTransactionIdIsValid

#define VirtualTransactionIdIsValid (   vxid)

Typedef Documentation

◆ BlockedProcData

◆ BlockedProcsData

◆ LOCALLOCK

◆ LOCALLOCKOWNER

◆ LOCALLOCKTAG

◆ LOCK

typedef struct LOCK LOCK

◆ LockData

◆ LockInstanceData

◆ LockMethod

Definition at line 119 of file lock.h.

◆ LockMethodData

◆ LOCKMETHODID

Definition at line 125 of file lock.h.

◆ LOCKTAG

◆ LockTagType

◆ PGPROC

Definition at line 28 of file lock.h.

◆ PROC_QUEUE

◆ PROCLOCK

◆ PROCLOCKTAG

Enumeration Type Documentation

◆ DeadLockState

Enumerator
DS_NOT_YET_CHECKED 
DS_NO_DEADLOCK 
DS_SOFT_DEADLOCK 
DS_HARD_DEADLOCK 
DS_BLOCKED_BY_AUTOVACUUM 

Definition at line 481 of file lock.h.

482 {
483  DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
484  DS_NO_DEADLOCK, /* no deadlock detected */
485  DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
486  DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
487  DS_BLOCKED_BY_AUTOVACUUM /* no deadlock; queue blocked by autovacuum
488  * worker */
489 } DeadLockState;
DeadLockState
Definition: lock.h:481

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 
LOCKACQUIRE_ALREADY_CLEAR 

Definition at line 472 of file lock.h.

473 {
474  LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
475  LOCKACQUIRE_OK, /* lock successfully acquired */
476  LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
477  LOCKACQUIRE_ALREADY_CLEAR /* incremented count for lock already clear */
LockAcquireResult
Definition: lock.h:472

◆ LockTagType

Enumerator
LOCKTAG_RELATION 
LOCKTAG_RELATION_EXTEND 
LOCKTAG_PAGE 
LOCKTAG_TUPLE 
LOCKTAG_TRANSACTION 
LOCKTAG_VIRTUALTRANSACTION 
LOCKTAG_SPECULATIVE_TOKEN 
LOCKTAG_OBJECT 
LOCKTAG_USERLOCK 
LOCKTAG_ADVISORY 

Definition at line 138 of file lock.h.

139 {
140  LOCKTAG_RELATION, /* whole relation */
141  /* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */
142  LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */
143  /* same ID info as RELATION */
144  LOCKTAG_PAGE, /* one page of a relation */
145  /* ID info for a page is RELATION info + BlockNumber */
146  LOCKTAG_TUPLE, /* one physical tuple */
147  /* ID info for a tuple is PAGE info + OffsetNumber */
148  LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */
149  /* ID info for a transaction is its TransactionId */
150  LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */
151  /* ID info for a virtual transaction is its VirtualTransactionId */
152  LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */
153  /* ID info for a transaction is its TransactionId */
154  LOCKTAG_OBJECT, /* non-relation database object */
155  /* ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID */
156 
157  /*
158  * Note: object ID has same representation as in pg_depend and
159  * pg_description, but notice that we are constraining SUBID to 16 bits.
160  * Also, we use DB OID = 0 for shared objects such as tablespaces.
161  */
162  LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */
163  LOCKTAG_ADVISORY /* advisory user locks */
164 } LockTagType;
LockTagType
Definition: lock.h:138

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )

Definition at line 1642 of file lock.c.

References Assert, FastPathStrongRelationLockData::count, FastPathStrongLockHashPartition, LOCALLOCK::hashcode, LOCALLOCK::holdsStrongLockCount, FastPathStrongRelationLockData::mutex, SpinLockAcquire, SpinLockRelease, and StrongLockInProgress.

Referenced by LockAcquireExtended(), and LockErrorCleanup().

1643 {
1644  uint32 fasthashcode;
1645  LOCALLOCK *locallock = StrongLockInProgress;
1646 
1647  if (locallock == NULL)
1648  return;
1649 
1650  fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1651  Assert(locallock->holdsStrongLockCount == true);
1653  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1654  FastPathStrongRelationLocks->count[fasthashcode]--;
1655  locallock->holdsStrongLockCount = false;
1656  StrongLockInProgress = NULL;
1658 }
uint32 hashcode
Definition: lock.h:409
bool holdsStrongLockCount
Definition: lock.h:411
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:259
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
unsigned int uint32
Definition: c.h:358
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:732

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

Definition at line 3110 of file lock.c.

References ereport, errcode(), errmsg(), ERROR, FastPathGetRelationLockEntry(), hash_seq_init(), hash_seq_search(), LOCALLOCK::holdsStrongLockCount, i, LOCALLOCKTAG::lock, LOCALLOCK::lock, TwoPhaseLockRecord::lockmode, LOCALLOCK::lockOwners, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_type, LOCKTAG_VIRTUALTRANSACTION, LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, LOCALLOCK::nLocks, LOCALLOCK::numLockOwners, LOCALLOCK::proclock, RegisterTwoPhaseRecord(), status(), PROCLOCK::tag, LOCALLOCK::tag, and TWOPHASE_RM_LOCK_ID.

Referenced by PrepareTransaction().

3111 {
3113  LOCALLOCK *locallock;
3114 
3115  /*
3116  * For the most part, we don't need to touch shared memory for this ---
3117  * all the necessary state information is in the locallock table.
3118  * Fast-path locks are an exception, however: we move any such locks to
3119  * the main table before allowing PREPARE TRANSACTION to succeed.
3120  */
3122 
3123  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3124  {
3125  TwoPhaseLockRecord record;
3126  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3127  bool haveSessionLock;
3128  bool haveXactLock;
3129  int i;
3130 
3131  /*
3132  * Ignore VXID locks. We don't want those to be held by prepared
3133  * transactions, since they aren't meaningful after a restart.
3134  */
3135  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3136  continue;
3137 
3138  /* Ignore it if we don't actually hold the lock */
3139  if (locallock->nLocks <= 0)
3140  continue;
3141 
3142  /* Scan to see whether we hold it at session or transaction level */
3143  haveSessionLock = haveXactLock = false;
3144  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3145  {
3146  if (lockOwners[i].owner == NULL)
3147  haveSessionLock = true;
3148  else
3149  haveXactLock = true;
3150  }
3151 
3152  /* Ignore it if we have only session lock */
3153  if (!haveXactLock)
3154  continue;
3155 
3156  /*
3157  * If we have both session- and transaction-level locks, fail. This
3158  * should never happen with regular locks, since we only take those at
3159  * session level in some special operations like VACUUM. It's
3160  * possible to hit this with advisory locks, though.
3161  *
3162  * It would be nice if we could keep the session hold and give away
3163  * the transactional hold to the prepared xact. However, that would
3164  * require two PROCLOCK objects, and we cannot be sure that another
3165  * PROCLOCK will be available when it comes time for PostPrepare_Locks
3166  * to do the deed. So for now, we error out while we can still do so
3167  * safely.
3168  */
3169  if (haveSessionLock)
3170  ereport(ERROR,
3171  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3172  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3173 
3174  /*
3175  * If the local lock was taken via the fast-path, we need to move it
3176  * to the primary lock table, or just get a pointer to the existing
3177  * primary lock table entry if by chance it's already been
3178  * transferred.
3179  */
3180  if (locallock->proclock == NULL)
3181  {
3182  locallock->proclock = FastPathGetRelationLockEntry(locallock);
3183  locallock->lock = locallock->proclock->tag.myLock;
3184  }
3185 
3186  /*
3187  * Arrange to not release any strong lock count held by this lock
3188  * entry. We must retain the count until the prepared transaction is
3189  * committed or rolled back.
3190  */
3191  locallock->holdsStrongLockCount = false;
3192 
3193  /*
3194  * Create a 2PC record.
3195  */
3196  memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3197  record.lockmode = locallock->tag.mode;
3198 
3200  &record, sizeof(TwoPhaseLockRecord));
3201  }
3202 }
PROCLOCKTAG tag
Definition: lock.h:347
LOCALLOCKTAG tag
Definition: lock.h:404
static HTAB * LockMethodLocalHash
Definition: lock.c:255
bool holdsStrongLockCount
Definition: lock.h:411
int numLockOwners
Definition: lock.h:413
LOCKTAG lock
Definition: lock.h:385
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition: lock.c:2695
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
Definition: lock.h:178
int errcode(int sqlerrcode)
Definition: elog.c:575
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1192
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
uint8 locktag_type
Definition: lock.h:184
#define TWOPHASE_RM_LOCK_ID
Definition: twophase_rmgr.h:25
LOCALLOCKOWNER * lockOwners
Definition: lock.h:415
LOCK * lock
Definition: lock.h:407
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int64 nLocks
Definition: lock.h:410
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
LOCK * myLock
Definition: lock.h:340
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
LOCKMODE lockmode
Definition: lock.c:161

◆ DeadLockCheck()

DeadLockState DeadLockCheck ( PGPROC proc)

Definition at line 217 of file deadlock.c.

References Assert, DeadLockCheckRecurse(), DS_BLOCKED_BY_AUTOVACUUM, DS_HARD_DEADLOCK, DS_NO_DEADLOCK, DS_SOFT_DEADLOCK, elog, FATAL, FindLockCycle(), GetLocksMethodTable(), i, PROC_QUEUE::links, PGPROC::links, WAIT_ORDER::lock, nCurConstraints, nPossibleConstraints, WAIT_ORDER::nProcs, nWaitOrders, ProcLockWakeup(), ProcQueueInit(), WAIT_ORDER::procs, SHMQueueInsertBefore(), PROC_QUEUE::size, and LOCK::waitProcs.

Referenced by CheckDeadLock().

218 {
219  int i,
220  j;
221 
222  /* Initialize to "no constraints" */
223  nCurConstraints = 0;
225  nWaitOrders = 0;
226 
227  /* Initialize to not blocked by an autovacuum worker */
229 
230  /* Search for deadlocks and possible fixes */
231  if (DeadLockCheckRecurse(proc))
232  {
233  /*
234  * Call FindLockCycle one more time, to record the correct
235  * deadlockDetails[] for the basic state with no rearrangements.
236  */
237  int nSoftEdges;
238 
239  TRACE_POSTGRESQL_DEADLOCK_FOUND();
240 
241  nWaitOrders = 0;
242  if (!FindLockCycle(proc, possibleConstraints, &nSoftEdges))
243  elog(FATAL, "deadlock seems to have disappeared");
244 
245  return DS_HARD_DEADLOCK; /* cannot find a non-deadlocked state */
246  }
247 
248  /* Apply any needed rearrangements of wait queues */
249  for (i = 0; i < nWaitOrders; i++)
250  {
251  LOCK *lock = waitOrders[i].lock;
252  PGPROC **procs = waitOrders[i].procs;
253  int nProcs = waitOrders[i].nProcs;
254  PROC_QUEUE *waitQueue = &(lock->waitProcs);
255 
256  Assert(nProcs == waitQueue->size);
257 
258 #ifdef DEBUG_DEADLOCK
259  PrintLockQueue(lock, "DeadLockCheck:");
260 #endif
261 
262  /* Reset the queue and re-add procs in the desired order */
263  ProcQueueInit(waitQueue);
264  for (j = 0; j < nProcs; j++)
265  {
266  SHMQueueInsertBefore(&(waitQueue->links), &(procs[j]->links));
267  waitQueue->size++;
268  }
269 
270 #ifdef DEBUG_DEADLOCK
271  PrintLockQueue(lock, "rearranged to:");
272 #endif
273 
274  /* See if any waiters for the lock can be woken up now */
275  ProcLockWakeup(GetLocksMethodTable(lock), lock);
276  }
277 
278  /* Return code tells caller if we had to escape a deadlock or not */
279  if (nWaitOrders > 0)
280  return DS_SOFT_DEADLOCK;
281  else if (blocking_autovacuum_proc != NULL)
283  else
284  return DS_NO_DEADLOCK;
285 }
static WAIT_ORDER * waitOrders
Definition: deadlock.c:111
SHM_QUEUE links
Definition: lock.h:32
SHM_QUEUE links
Definition: proc.h:98
static PGPROC * blocking_autovacuum_proc
Definition: deadlock.c:128
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static int nCurConstraints
Definition: deadlock.c:117
static int nPossibleConstraints
Definition: deadlock.c:122
int nProcs
Definition: deadlock.c:60
PROC_QUEUE waitProcs
Definition: lock.h:293
LOCK * lock
Definition: deadlock.c:58
static bool FindLockCycle(PGPROC *checkProc, EDGE *softEdges, int *nSoftEdges)
Definition: deadlock.c:449
PGPROC ** procs
Definition: deadlock.c:59
#define FATAL
Definition: elog.h:52
void ProcQueueInit(PROC_QUEUE *queue)
Definition: proc.c:1015
Definition: lock.h:284
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1606
#define Assert(condition)
Definition: c.h:732
static EDGE * possibleConstraints
Definition: deadlock.c:121
static bool DeadLockCheckRecurse(PGPROC *proc)
Definition: deadlock.c:315
#define elog(elevel,...)
Definition: elog.h:226
int i
int size
Definition: lock.h:33
static int nWaitOrders
Definition: deadlock.c:112
Definition: proc.h:95
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition: lock.c:460

◆ DeadLockReport()

void DeadLockReport ( void  )

Definition at line 1077 of file deadlock.c.

References _, appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), StringInfoData::data, DescribeLockTag(), ereport, errcode(), errdetail_internal(), errdetail_log(), errhint(), errmsg(), ERROR, GetLockmodeName(), i, initStringInfo(), DEADLOCK_INFO::lockmode, DEADLOCK_INFO::locktag, LOCKTAG::locktag_lockmethodid, nDeadlockDetails, pgstat_get_backend_current_activity(), pgstat_report_deadlock(), DEADLOCK_INFO::pid, and resetStringInfo().

Referenced by WaitOnLock().

1078 {
1079  StringInfoData clientbuf; /* errdetail for client */
1080  StringInfoData logbuf; /* errdetail for server log */
1081  StringInfoData locktagbuf;
1082  int i;
1083 
1084  initStringInfo(&clientbuf);
1085  initStringInfo(&logbuf);
1086  initStringInfo(&locktagbuf);
1087 
1088  /* Generate the "waits for" lines sent to the client */
1089  for (i = 0; i < nDeadlockDetails; i++)
1090  {
1091  DEADLOCK_INFO *info = &deadlockDetails[i];
1092  int nextpid;
1093 
1094  /* The last proc waits for the first one... */
1095  if (i < nDeadlockDetails - 1)
1096  nextpid = info[1].pid;
1097  else
1098  nextpid = deadlockDetails[0].pid;
1099 
1100  /* reset locktagbuf to hold next object description */
1101  resetStringInfo(&locktagbuf);
1102 
1103  DescribeLockTag(&locktagbuf, &info->locktag);
1104 
1105  if (i > 0)
1106  appendStringInfoChar(&clientbuf, '\n');
1107 
1108  appendStringInfo(&clientbuf,
1109  _("Process %d waits for %s on %s; blocked by process %d."),
1110  info->pid,
1112  info->lockmode),
1113  locktagbuf.data,
1114  nextpid);
1115  }
1116 
1117  /* Duplicate all the above for the server ... */
1118  appendStringInfoString(&logbuf, clientbuf.data);
1119 
1120  /* ... and add info about query strings */
1121  for (i = 0; i < nDeadlockDetails; i++)
1122  {
1123  DEADLOCK_INFO *info = &deadlockDetails[i];
1124 
1125  appendStringInfoChar(&logbuf, '\n');
1126 
1127  appendStringInfo(&logbuf,
1128  _("Process %d: %s"),
1129  info->pid,
1131  }
1132 
1134 
1135  ereport(ERROR,
1136  (errcode(ERRCODE_T_R_DEADLOCK_DETECTED),
1137  errmsg("deadlock detected"),
1138  errdetail_internal("%s", clientbuf.data),
1139  errdetail_log("%s", logbuf.data),
1140  errhint("See server log for query details.")));
1141 }
void pgstat_report_deadlock(void)
Definition: pgstat.c:1506
int errhint(const char *fmt,...)
Definition: elog.c:987
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:3896
LOCKMODE lockmode
Definition: deadlock.c:74
int errcode(int sqlerrcode)
Definition: elog.c:575
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:78
#define ERROR
Definition: elog.h:43
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1002
static int nDeadlockDetails
Definition: deadlock.c:125
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:62
int errdetail_log(const char *fmt,...)
Definition: elog.c:921
#define ereport(elevel, rest)
Definition: elog.h:141
const char * pgstat_get_backend_current_activity(int pid, bool checkUser)
Definition: pgstat.c:3965
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
static DEADLOCK_INFO * deadlockDetails
Definition: deadlock.c:124
uint8 locktag_lockmethodid
Definition: lock.h:185
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
LOCKTAG locktag
Definition: deadlock.c:73
#define _(x)
Definition: elog.c:84

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 556 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

Referenced by Do_MultiXactIdWait(), DoesMultiXactIdConflict(), initialize_reloptions(), and test_lockmode_for_conflict().

557 {
558  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
559 
560  if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
561  return true;
562 
563  return false;
564 }
const LOCKMASK * conflictTab
Definition: lock.h:114
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

Definition at line 3633 of file lock.c.

References Assert, BackendPidGetProcWithLock(), dlist_iter::cur, dlist_container, dlist_foreach, GetSingleProcBlockerStatusData(), i, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LockHashPartitionLockByIndex, BlockedProcsData::locks, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaxBackends, BlockedProcsData::maxlocks, BlockedProcsData::maxpids, BlockedProcsData::maxprocs, BlockedProcsData::nlocks, BlockedProcsData::npids, BlockedProcsData::nprocs, NUM_LOCK_PARTITIONS, palloc(), BlockedProcsData::procs, and BlockedProcsData::waiter_pids.

Referenced by pg_blocking_pids().

3634 {
3635  BlockedProcsData *data;
3636  PGPROC *proc;
3637  int i;
3638 
3639  data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
3640 
3641  /*
3642  * Guess how much space we'll need, and preallocate. Most of the time
3643  * this will avoid needing to do repalloc while holding the LWLocks. (We
3644  * assume, but check with an Assert, that MaxBackends is enough entries
3645  * for the procs[] array; the other two could need enlargement, though.)
3646  */
3647  data->nprocs = data->nlocks = data->npids = 0;
3648  data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3649  data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
3650  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3651  data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3652 
3653  /*
3654  * In order to search the ProcArray for blocked_pid and assume that that
3655  * entry won't immediately disappear under us, we must hold ProcArrayLock.
3656  * In addition, to examine the lock grouping fields of any other backend,
3657  * we must hold all the hash partition locks. (Only one of those locks is
3658  * actually relevant for any one lock group, but we can't know which one
3659  * ahead of time.) It's fairly annoying to hold all those locks
3660  * throughout this, but it's no worse than GetLockStatusData(), and it
3661  * does have the advantage that we're guaranteed to return a
3662  * self-consistent instantaneous state.
3663  */
3664  LWLockAcquire(ProcArrayLock, LW_SHARED);
3665 
3666  proc = BackendPidGetProcWithLock(blocked_pid);
3667 
3668  /* Nothing to do if it's gone */
3669  if (proc != NULL)
3670  {
3671  /*
3672  * Acquire lock on the entire shared lock data structure. See notes
3673  * in GetLockStatusData().
3674  */
3675  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3677 
3678  if (proc->lockGroupLeader == NULL)
3679  {
3680  /* Easy case, proc is not a lock group member */
3681  GetSingleProcBlockerStatusData(proc, data);
3682  }
3683  else
3684  {
3685  /* Examine all procs in proc's lock group */
3686  dlist_iter iter;
3687 
3689  {
3690  PGPROC *memberProc;
3691 
3692  memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
3693  GetSingleProcBlockerStatusData(memberProc, data);
3694  }
3695  }
3696 
3697  /*
3698  * And release locks. See notes in GetLockStatusData().
3699  */
3700  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3702 
3703  Assert(data->nprocs <= data->maxprocs);
3704  }
3705 
3706  LWLockRelease(ProcArrayLock);
3707 
3708  return data;
3709 }
int * waiter_pids
Definition: lock.h:461
dlist_head lockGroupMembers
Definition: proc.h:204
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
BlockedProcData * procs
Definition: lock.h:459
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2371
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition: lock.c:3713
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
int MaxBackends
Definition: globals.c:134
int maxlocks
Definition: lock.h:465
LockInstanceData * locks
Definition: lock.h:460
dlist_node * cur
Definition: ilist.h:161
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void * palloc(Size size)
Definition: mcxt.c:924
int i
Definition: proc.h:95
PGPROC * lockGroupLeader
Definition: proc.h:203
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
int maxprocs
Definition: lock.h:463

◆ GetBlockingAutoVacuumPgproc()

PGPROC* GetBlockingAutoVacuumPgproc ( void  )

Definition at line 293 of file deadlock.c.

References blocking_autovacuum_proc.

Referenced by ProcSleep().

294 {
295  PGPROC *ptr;
296 
299 
300  return ptr;
301 }
static PGPROC * blocking_autovacuum_proc
Definition: deadlock.c:128
Definition: proc.h:95

◆ GetLockConflicts()

VirtualTransactionId* GetLockConflicts ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 2796 of file lock.c.

References PROC_HDR::allProcCount, PROC_HDR::allProcs, VirtualTransactionId::backendId, PGPROC::backendLock, ConflictsWithRelationFastPath, LockMethodData::conflictTab, PGPROC::databaseId, elog, ERROR, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpRelId, GET_VXID_FROM_PGPROC, HASH_FIND, hash_search_with_hash_value(), PROCLOCK::holdMask, i, InHotStandby, InvalidBackendId, InvalidLocalTransactionId, lengthof, VirtualTransactionId::localTransactionId, LockHashPartitionLock, PROCLOCK::lockLink, TwoPhaseLockRecord::lockmode, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LockTagHashCode(), LW_SHARED, LWLockAcquire(), LWLockRelease(), MaxBackends, MemoryContextAlloc(), MyProc, PROCLOCKTAG::myProc, LockMethodData::numLockModes, offsetof, palloc0(), PANIC, ProcGlobal, LOCK::procLocks, SHMQueueNext(), PROCLOCK::tag, TopMemoryContext, VirtualTransactionIdEquals, and VirtualTransactionIdIsValid.

Referenced by ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

2797 {
2798  static VirtualTransactionId *vxids;
2799  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
2800  LockMethod lockMethodTable;
2801  LOCK *lock;
2802  LOCKMASK conflictMask;
2803  SHM_QUEUE *procLocks;
2804  PROCLOCK *proclock;
2805  uint32 hashcode;
2806  LWLock *partitionLock;
2807  int count = 0;
2808  int fast_count = 0;
2809 
2810  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2811  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2812  lockMethodTable = LockMethods[lockmethodid];
2813  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2814  elog(ERROR, "unrecognized lock mode: %d", lockmode);
2815 
2816  /*
2817  * Allocate memory to store results, and fill with InvalidVXID. We only
2818  * need enough space for MaxBackends + a terminator, since prepared xacts
2819  * don't count. InHotStandby allocate once in TopMemoryContext.
2820  */
2821  if (InHotStandby)
2822  {
2823  if (vxids == NULL)
2824  vxids = (VirtualTransactionId *)
2826  sizeof(VirtualTransactionId) * (MaxBackends + 1));
2827  }
2828  else
2829  vxids = (VirtualTransactionId *)
2830  palloc0(sizeof(VirtualTransactionId) * (MaxBackends + 1));
2831 
2832  /* Compute hash code and partition lock, and look up conflicting modes. */
2833  hashcode = LockTagHashCode(locktag);
2834  partitionLock = LockHashPartitionLock(hashcode);
2835  conflictMask = lockMethodTable->conflictTab[lockmode];
2836 
2837  /*
2838  * Fast path locks might not have been entered in the primary lock table.
2839  * If the lock we're dealing with could conflict with such a lock, we must
2840  * examine each backend's fast-path array for conflicts.
2841  */
2842  if (ConflictsWithRelationFastPath(locktag, lockmode))
2843  {
2844  int i;
2845  Oid relid = locktag->locktag_field2;
2846  VirtualTransactionId vxid;
2847 
2848  /*
2849  * Iterate over relevant PGPROCs. Anything held by a prepared
2850  * transaction will have been transferred to the primary lock table,
2851  * so we need not worry about those. This is all a bit fuzzy, because
2852  * new locks could be taken after we've visited a particular
2853  * partition, but the callers had better be prepared to deal with that
2854  * anyway, since the locks could equally well be taken between the
2855  * time we return the value and the time the caller does something
2856  * with it.
2857  */
2858  for (i = 0; i < ProcGlobal->allProcCount; i++)
2859  {
2860  PGPROC *proc = &ProcGlobal->allProcs[i];
2861  uint32 f;
2862 
2863  /* A backend never blocks itself */
2864  if (proc == MyProc)
2865  continue;
2866 
2868 
2869  /*
2870  * If the target backend isn't referencing the same database as
2871  * the lock, then we needn't examine the individual relation IDs
2872  * at all; none of them can be relevant.
2873  *
2874  * See FastPathTransferLocks() for discussion of why we do this
2875  * test after acquiring the lock.
2876  */
2877  if (proc->databaseId != locktag->locktag_field1)
2878  {
2879  LWLockRelease(&proc->backendLock);
2880  continue;
2881  }
2882 
2883  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2884  {
2885  uint32 lockmask;
2886 
2887  /* Look for an allocated slot matching the given relid. */
2888  if (relid != proc->fpRelId[f])
2889  continue;
2890  lockmask = FAST_PATH_GET_BITS(proc, f);
2891  if (!lockmask)
2892  continue;
2893  lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
2894 
2895  /*
2896  * There can only be one entry per relation, so if we found it
2897  * and it doesn't conflict, we can skip the rest of the slots.
2898  */
2899  if ((lockmask & conflictMask) == 0)
2900  break;
2901 
2902  /* Conflict! */
2903  GET_VXID_FROM_PGPROC(vxid, *proc);
2904 
2905  /*
2906  * If we see an invalid VXID, then either the xact has already
2907  * committed (or aborted), or it's a prepared xact. In either
2908  * case we may ignore it.
2909  */
2910  if (VirtualTransactionIdIsValid(vxid))
2911  vxids[count++] = vxid;
2912 
2913  /* No need to examine remaining slots. */
2914  break;
2915  }
2916 
2917  LWLockRelease(&proc->backendLock);
2918  }
2919  }
2920 
2921  /* Remember how many fast-path conflicts we found. */
2922  fast_count = count;
2923 
2924  /*
2925  * Look up the lock object matching the tag.
2926  */
2927  LWLockAcquire(partitionLock, LW_SHARED);
2928 
2930  (const void *) locktag,
2931  hashcode,
2932  HASH_FIND,
2933  NULL);
2934  if (!lock)
2935  {
2936  /*
2937  * If the lock object doesn't exist, there is nothing holding a lock
2938  * on this lockable object.
2939  */
2940  LWLockRelease(partitionLock);
2941  vxids[count].backendId = InvalidBackendId;
2943  return vxids;
2944  }
2945 
2946  /*
2947  * Examine each existing holder (or awaiter) of the lock.
2948  */
2949 
2950  procLocks = &(lock->procLocks);
2951 
2952  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2953  offsetof(PROCLOCK, lockLink));
2954 
2955  while (proclock)
2956  {
2957  if (conflictMask & proclock->holdMask)
2958  {
2959  PGPROC *proc = proclock->tag.myProc;
2960 
2961  /* A backend never blocks itself */
2962  if (proc != MyProc)
2963  {
2964  VirtualTransactionId vxid;
2965 
2966  GET_VXID_FROM_PGPROC(vxid, *proc);
2967 
2968  /*
2969  * If we see an invalid VXID, then either the xact has already
2970  * committed (or aborted), or it's a prepared xact. In either
2971  * case we may ignore it.
2972  */
2973  if (VirtualTransactionIdIsValid(vxid))
2974  {
2975  int i;
2976 
2977  /* Avoid duplicate entries. */
2978  for (i = 0; i < fast_count; ++i)
2979  if (VirtualTransactionIdEquals(vxids[i], vxid))
2980  break;
2981  if (i >= fast_count)
2982  vxids[count++] = vxid;
2983  }
2984  }
2985  }
2986 
2987  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
2988  offsetof(PROCLOCK, lockLink));
2989  }
2990 
2991  LWLockRelease(partitionLock);
2992 
2993  if (count > MaxBackends) /* should never happen */
2994  elog(PANIC, "too many conflicting locks found");
2995 
2996  vxids[count].backendId = InvalidBackendId;
2998  return vxids;
2999 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
PROCLOCKTAG tag
Definition: lock.h:347
Definition: lwlock.h:32
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
const LOCKMASK * conflictTab
Definition: lock.h:114
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
SHM_QUEUE lockLink
Definition: lock.h:353
#define InHotStandby
Definition: xlog.h:74
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define lengthof(array)
Definition: c.h:662
unsigned int Oid
Definition: postgres_ext.h:31
LocalTransactionId localTransactionId
Definition: lock.h:66
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:74
#define ERROR
Definition: elog.h:43
int MaxBackends
Definition: globals.c:134
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
uint32 locktag_field2
Definition: lock.h:181
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:358
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
MemoryContext TopMemoryContext
Definition: mcxt.c:44
uint16 LOCKMETHODID
Definition: lock.h:125
SHM_QUEUE procLocks
Definition: lock.h:292
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:955
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
BackendId backendId
Definition: lock.h:65
LWLock backendLock
Definition: proc.h:190
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
uint32 allProcCount
Definition: proc.h:251
int LOCKMASK
Definition: lockdefs.h:25
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
Definition: lock.h:344
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
#define elog(elevel,...)
Definition: elog.h:226
#define InvalidLocalTransactionId
Definition: lock.h:69
int i
PGPROC * allProcs
Definition: proc.h:247
static const LockMethod LockMethods[]
Definition: lock.c:150
uint32 locktag_field1
Definition: lock.h:180
Definition: proc.h:95
#define offsetof(type, field)
Definition: c.h:655
int numLockModes
Definition: lock.h:113

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

Definition at line 3896 of file lock.c.

References Assert, elog, hash_seq_init(), hash_seq_search(), i, lengthof, LOCK_PRINT, LockMethodData::lockModeNames, LOG, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, PGPROC::myProcLocks, NUM_LOCK_PARTITIONS, offsetof, PROCLOCK::procLink, PROCLOCK_PRINT, SHMQueueNext(), status(), PROCLOCK::tag, and PGPROC::waitLock.

Referenced by DeadLockReport(), pg_lock_status(), and ProcSleep().

3897 {
3898  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
3899  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
3900  return LockMethods[lockmethodid]->lockModeNames[mode];
3901 }
#define lengthof(array)
Definition: c.h:662
#define Assert(condition)
Definition: c.h:732
static const LockMethod LockMethods[]
Definition: lock.c:150
const char *const * lockModeNames
Definition: lock.h:115

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)

Definition at line 460 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

461 {
462  LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
463 
464  Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
465  return LockMethods[lockmethodid];
466 }
#define lengthof(array)
Definition: c.h:662
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:732
static const LockMethod LockMethods[]
Definition: lock.c:150
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:300

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

Definition at line 3449 of file lock.c.

References PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert, LockInstanceData::backend, VirtualTransactionId::backendId, PGPROC::backendId, PGPROC::backendLock, PGPROC::databaseId, ExclusiveLock, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, LockInstanceData::fastpath, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpLocalTransactionId, PGPROC::fpRelId, PGPROC::fpVXIDLock, PROCLOCK::groupLeader, hash_get_num_entries(), hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, LockInstanceData::holdMask, i, LockInstanceData::leaderPid, VirtualTransactionId::localTransactionId, LOCKBIT_ON, LockHashPartitionLockByIndex, LockData::locks, LockInstanceData::locktag, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, LockInstanceData::lxid, MaxBackends, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, LockData::nelements, NoLock, NUM_LOCK_PARTITIONS, palloc(), PGPROC::pid, LockInstanceData::pid, ProcGlobal, repalloc(), SET_LOCKTAG_RELATION, SET_LOCKTAG_VIRTUALTRANSACTION, LOCK::tag, PROCLOCK::tag, PGPROC::waitLock, PGPROC::waitLockMode, and LockInstanceData::waitLockMode.

Referenced by pg_lock_status().

3450 {
3451  LockData *data;
3452  PROCLOCK *proclock;
3453  HASH_SEQ_STATUS seqstat;
3454  int els;
3455  int el;
3456  int i;
3457 
3458  data = (LockData *) palloc(sizeof(LockData));
3459 
3460  /* Guess how much space we'll need. */
3461  els = MaxBackends;
3462  el = 0;
3463  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3464 
3465  /*
3466  * First, we iterate through the per-backend fast-path arrays, locking
3467  * them one at a time. This might produce an inconsistent picture of the
3468  * system state, but taking all of those LWLocks at the same time seems
3469  * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3470  * matter too much, because none of these locks can be involved in lock
3471  * conflicts anyway - anything that might must be present in the main lock
3472  * table. (For the same reason, we don't sweat about making leaderPid
3473  * completely valid. We cannot safely dereference another backend's
3474  * lockGroupLeader field without holding all lock partition locks, and
3475  * it's not worth that.)
3476  */
3477  for (i = 0; i < ProcGlobal->allProcCount; ++i)
3478  {
3479  PGPROC *proc = &ProcGlobal->allProcs[i];
3480  uint32 f;
3481 
3483 
3484  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
3485  {
3486  LockInstanceData *instance;
3487  uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3488 
3489  /* Skip unallocated slots. */
3490  if (!lockbits)
3491  continue;
3492 
3493  if (el >= els)
3494  {
3495  els += MaxBackends;
3496  data->locks = (LockInstanceData *)
3497  repalloc(data->locks, sizeof(LockInstanceData) * els);
3498  }
3499 
3500  instance = &data->locks[el];
3501  SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3502  proc->fpRelId[f]);
3503  instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3504  instance->waitLockMode = NoLock;
3505  instance->backend = proc->backendId;
3506  instance->lxid = proc->lxid;
3507  instance->pid = proc->pid;
3508  instance->leaderPid = proc->pid;
3509  instance->fastpath = true;
3510 
3511  el++;
3512  }
3513 
3514  if (proc->fpVXIDLock)
3515  {
3516  VirtualTransactionId vxid;
3517  LockInstanceData *instance;
3518 
3519  if (el >= els)
3520  {
3521  els += MaxBackends;
3522  data->locks = (LockInstanceData *)
3523  repalloc(data->locks, sizeof(LockInstanceData) * els);
3524  }
3525 
3526  vxid.backendId = proc->backendId;
3528 
3529  instance = &data->locks[el];
3530  SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3531  instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3532  instance->waitLockMode = NoLock;
3533  instance->backend = proc->backendId;
3534  instance->lxid = proc->lxid;
3535  instance->pid = proc->pid;
3536  instance->leaderPid = proc->pid;
3537  instance->fastpath = true;
3538 
3539  el++;
3540  }
3541 
3542  LWLockRelease(&proc->backendLock);
3543  }
3544 
3545  /*
3546  * Next, acquire lock on the entire shared lock data structure. We do
3547  * this so that, at least for locks in the primary lock table, the state
3548  * will be self-consistent.
3549  *
3550  * Since this is a read-only operation, we take shared instead of
3551  * exclusive lock. There's not a whole lot of point to this, because all
3552  * the normal operations require exclusive lock, but it doesn't hurt
3553  * anything either. It will at least allow two backends to do
3554  * GetLockStatusData in parallel.
3555  *
3556  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3557  */
3558  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3560 
3561  /* Now we can safely count the number of proclocks */
3563  if (data->nelements > els)
3564  {
3565  els = data->nelements;
3566  data->locks = (LockInstanceData *)
3567  repalloc(data->locks, sizeof(LockInstanceData) * els);
3568  }
3569 
3570  /* Now scan the tables to copy the data */
3572 
3573  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3574  {
3575  PGPROC *proc = proclock->tag.myProc;
3576  LOCK *lock = proclock->tag.myLock;
3577  LockInstanceData *instance = &data->locks[el];
3578 
3579  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3580  instance->holdMask = proclock->holdMask;
3581  if (proc->waitLock == proclock->tag.myLock)
3582  instance->waitLockMode = proc->waitLockMode;
3583  else
3584  instance->waitLockMode = NoLock;
3585  instance->backend = proc->backendId;
3586  instance->lxid = proc->lxid;
3587  instance->pid = proc->pid;
3588  instance->leaderPid = proclock->groupLeader->pid;
3589  instance->fastpath = false;
3590 
3591  el++;
3592  }
3593 
3594  /*
3595  * And release locks. We do this in reverse order for two reasons: (1)
3596  * Anyone else who needs more than one of the locks will be trying to lock
3597  * them in increasing order; we don't want to release the other process
3598  * until it can get all the locks it needs. (2) This avoids O(N^2)
3599  * behavior inside LWLockRelease.
3600  */
3601  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3603 
3604  Assert(el == data->nelements);
3605 
3606  return data;
3607 }
PROCLOCKTAG tag
Definition: lock.h:347
LockInstanceData * locks
Definition: lock.h:441
BackendId backendId
Definition: proc.h:113
#define ExclusiveLock
Definition: lockdefs.h:44
LOCKMASK holdMask
Definition: lock.h:351
bool fastpath
Definition: lock.h:435
LOCKMODE waitLockMode
Definition: proc.h:141
LOCKTAG tag
Definition: lock.h:287
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
Definition: lock.h:178
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1335
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
bool fpVXIDLock
Definition: proc.h:195
Definition: lock.h:438
LocalTransactionId localTransactionId
Definition: lock.h:66
LOCKTAG locktag
Definition: lock.h:428
LOCKMODE waitLockMode
Definition: lock.h:430
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
int leaderPid
Definition: lock.h:434
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
int MaxBackends
Definition: globals.c:134
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:193
#define NoLock
Definition: lockdefs.h:34
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:358
Definition: lock.h:284
LOCK * waitLock
Definition: proc.h:139
int nelements
Definition: lock.h:440
BackendId backend
Definition: lock.h:431
LocalTransactionId lxid
Definition: lock.h:432
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
#define Assert(condition)
Definition: c.h:732
BackendId backendId
Definition: lock.h:65
LWLock backendLock
Definition: proc.h:190
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition: lock.h:233
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
uint32 allProcCount
Definition: proc.h:251
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
LOCKMASK holdMask
Definition: lock.h:429
PGPROC * myProc
Definition: lock.h:341
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
void * palloc(Size size)
Definition: mcxt.c:924
int i
LOCK * myLock
Definition: lock.h:340
PGPROC * allProcs
Definition: proc.h:247
Definition: proc.h:95
int pid
Definition: proc.h:109
LocalTransactionId fpLocalTransactionId
Definition: proc.h:196
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
PGPROC * groupLeader
Definition: lock.h:350
LocalTransactionId lxid
Definition: proc.h:106

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 472 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

473 {
474  LOCKMETHODID lockmethodid = (LOCKMETHODID) locktag->locktag_lockmethodid;
475 
476  Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
477  return LockMethods[lockmethodid];
478 }
#define lengthof(array)
Definition: c.h:662
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:732
uint8 locktag_lockmethodid
Definition: lock.h:185
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

Definition at line 3813 of file lock.c.

References AccessExclusiveLock, PROC_HDR::allPgXact, Assert, xl_standby_lock::dbOid, hash_get_num_entries(), hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, i, LOCKBIT_ON, LockHashPartitionLockByIndex, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG_RELATION, LOCKTAG::locktag_type, LW_SHARED, LWLockAcquire(), LWLockRelease(), PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, NUM_LOCK_PARTITIONS, palloc(), PGPROC::pgprocno, ProcGlobal, xl_standby_lock::relOid, LOCK::tag, PROCLOCK::tag, TransactionIdIsValid, xl_standby_lock::xid, and PGXACT::xid.

Referenced by LogStandbySnapshot().

3814 {
3815  xl_standby_lock *accessExclusiveLocks;
3816  PROCLOCK *proclock;
3817  HASH_SEQ_STATUS seqstat;
3818  int i;
3819  int index;
3820  int els;
3821 
3822  /*
3823  * Acquire lock on the entire shared lock data structure.
3824  *
3825  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3826  */
3827  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3829 
3830  /* Now we can safely count the number of proclocks */
3832 
3833  /*
3834  * Allocating enough space for all locks in the lock table is overkill,
3835  * but it's more convenient and faster than having to enlarge the array.
3836  */
3837  accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
3838 
3839  /* Now scan the tables to copy the data */
3841 
3842  /*
3843  * If lock is a currently granted AccessExclusiveLock then it will have
3844  * just one proclock holder, so locks are never accessed twice in this
3845  * particular case. Don't copy this code for use elsewhere because in the
3846  * general case this will give you duplicate locks when looking at
3847  * non-exclusive lock types.
3848  */
3849  index = 0;
3850  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3851  {
3852  /* make sure this definition matches the one used in LockAcquire */
3853  if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
3854  proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION)
3855  {
3856  PGPROC *proc = proclock->tag.myProc;
3857  PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno];
3858  LOCK *lock = proclock->tag.myLock;
3859  TransactionId xid = pgxact->xid;
3860 
3861  /*
3862  * Don't record locks for transactions if we know they have
3863  * already issued their WAL record for commit but not yet released
3864  * lock. It is still possible that we see locks held by already
3865  * complete transactions, if they haven't yet zeroed their xids.
3866  */
3867  if (!TransactionIdIsValid(xid))
3868  continue;
3869 
3870  accessExclusiveLocks[index].xid = xid;
3871  accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
3872  accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
3873 
3874  index++;
3875  }
3876  }
3877 
3878  Assert(index <= els);
3879 
3880  /*
3881  * And release locks. We do this in reverse order for two reasons: (1)
3882  * Anyone else who needs more than one of the locks will be trying to lock
3883  * them in increasing order; we don't want to release the other process
3884  * until it can get all the locks it needs. (2) This avoids O(N^2)
3885  * behavior inside LWLockRelease.
3886  */
3887  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3889 
3890  *nlocks = index;
3891  return accessExclusiveLocks;
3892 }
PROCLOCKTAG tag
Definition: lock.h:347
uint32 TransactionId
Definition: c.h:507
Definition: proc.h:222
PGXACT * allPgXact
Definition: proc.h:249
LOCKMASK holdMask
Definition: lock.h:351
TransactionId xid
Definition: proc.h:224
LOCKTAG tag
Definition: lock.h:287
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1335
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
uint32 locktag_field2
Definition: lock.h:181
Definition: lock.h:284
TransactionId xid
Definition: lockdefs.h:50
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:732
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: lock.h:344
int pgprocno
Definition: proc.h:110
void * palloc(Size size)
Definition: mcxt.c:924
int i
LOCK * myLock
Definition: lock.h:340
#define TransactionIdIsValid(xid)
Definition: transam.h:41
uint32 locktag_field1
Definition: lock.h:180
Definition: proc.h:95
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1671 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

1672 {
1674 }
static LOCALLOCK * awaitedLock
Definition: lock.c:260
static ResourceOwner awaitedOwner
Definition: lock.c:261
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1577

◆ GrantLock()

void GrantLock ( LOCK lock,
PROCLOCK proclock,
LOCKMODE  lockmode 
)

Definition at line 1443 of file lock.c.

References Assert, LOCK::granted, LOCK::grantMask, PROCLOCK::holdMask, LOCK_PRINT, LOCKBIT_OFF, LOCKBIT_ON, TwoPhaseLockRecord::lockmode, LOCK::nGranted, LOCK::nRequested, LOCK::requested, and LOCK::waitMask.

Referenced by FastPathGetRelationLockEntry(), FastPathTransferRelationLocks(), lock_twophase_recover(), LockAcquireExtended(), ProcLockWakeup(), ProcSleep(), and VirtualXactLock().

1444 {
1445  lock->nGranted++;
1446  lock->granted[lockmode]++;
1447  lock->grantMask |= LOCKBIT_ON(lockmode);
1448  if (lock->granted[lockmode] == lock->requested[lockmode])
1449  lock->waitMask &= LOCKBIT_OFF(lockmode);
1450  proclock->holdMask |= LOCKBIT_ON(lockmode);
1451  LOCK_PRINT("GrantLock", lock, lockmode);
1452  Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1453  Assert(lock->nGranted <= lock->nRequested);
1454 }
int nRequested
Definition: lock.h:295
LOCKMASK holdMask
Definition: lock.h:351
int nGranted
Definition: lock.h:297
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:88
int granted[MAX_LOCKMODES]
Definition: lock.h:296
LOCKMASK waitMask
Definition: lock.h:291
int requested[MAX_LOCKMODES]
Definition: lock.h:294
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:732
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290

◆ InitDeadLockChecking()

void InitDeadLockChecking ( void  )

Definition at line 143 of file deadlock.c.

References afterConstraints, beforeConstraints, MaxBackends, maxCurConstraints, maxPossibleConstraints, MemoryContextSwitchTo(), palloc(), TopMemoryContext, and visitedProcs.

Referenced by InitProcess().

144 {
145  MemoryContext oldcxt;
146 
147  /* Make sure allocations are permanent */
149 
150  /*
151  * FindLockCycle needs at most MaxBackends entries in visitedProcs[] and
152  * deadlockDetails[].
153  */
154  visitedProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
156 
157  /*
158  * TopoSort needs to consider at most MaxBackends wait-queue entries, and
159  * it needn't run concurrently with FindLockCycle.
160  */
161  topoProcs = visitedProcs; /* re-use this space */
162  beforeConstraints = (int *) palloc(MaxBackends * sizeof(int));
163  afterConstraints = (int *) palloc(MaxBackends * sizeof(int));
164 
165  /*
166  * We need to consider rearranging at most MaxBackends/2 wait queues
167  * (since it takes at least two waiters in a queue to create a soft edge),
168  * and the expanded form of the wait queues can't involve more than
169  * MaxBackends total waiters.
170  */
171  waitOrders = (WAIT_ORDER *)
172  palloc((MaxBackends / 2) * sizeof(WAIT_ORDER));
173  waitOrderProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
174 
175  /*
176  * Allow at most MaxBackends distinct constraints in a configuration. (Is
177  * this enough? In practice it seems it should be, but I don't quite see
178  * how to prove it. If we run out, we might fail to find a workable wait
179  * queue rearrangement even though one exists.) NOTE that this number
180  * limits the maximum recursion depth of DeadLockCheckRecurse. Making it
181  * really big might potentially allow a stack-overflow problem.
182  */
185 
186  /*
187  * Allow up to 3*MaxBackends constraints to be saved without having to
188  * re-run TestConfiguration. (This is probably more than enough, but we
189  * can survive if we run low on space by doing excess runs of
190  * TestConfiguration to re-compute constraint lists each time needed.) The
191  * last MaxBackends entries in possibleConstraints[] are reserved as
192  * output workspace for FindLockCycle.
193  */
196  (EDGE *) palloc(maxPossibleConstraints * sizeof(EDGE));
197 
198  MemoryContextSwitchTo(oldcxt);
199 }
static int maxCurConstraints
Definition: deadlock.c:118
static WAIT_ORDER * waitOrders
Definition: deadlock.c:111
Definition: deadlock.c:46
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static PGPROC ** waitOrderProcs
Definition: deadlock.c:113
static PGPROC ** topoProcs
Definition: deadlock.c:106
int MaxBackends
Definition: globals.c:134
static EDGE * curConstraints
Definition: deadlock.c:116
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static int * afterConstraints
Definition: deadlock.c:108
static DEADLOCK_INFO * deadlockDetails
Definition: deadlock.c:124
static PGPROC ** visitedProcs
Definition: deadlock.c:102
static EDGE * possibleConstraints
Definition: deadlock.c:121
void * palloc(Size size)
Definition: mcxt.c:924
static int maxPossibleConstraints
Definition: deadlock.c:123
static int * beforeConstraints
Definition: deadlock.c:107
Definition: proc.h:95

◆ InitLocks()

void InitLocks ( void  )

Definition at line 377 of file lock.c.

References HASHCTL::entrysize, HASHCTL::hash, HASH_BLOBS, hash_create(), hash_destroy(), HASH_ELEM, HASH_FUNCTION, HASH_PARTITION, HASHCTL::keysize, MemSet, FastPathStrongRelationLockData::mutex, NLOCKENTS, NUM_LOCK_PARTITIONS, HASHCTL::num_partitions, proclock_hash(), ShmemInitHash(), ShmemInitStruct(), and SpinLockInit.

Referenced by CreateSharedMemoryAndSemaphores().

378 {
379  HASHCTL info;
380  long init_table_size,
381  max_table_size;
382  bool found;
383 
384  /*
385  * Compute init/max size to request for lock hashtables. Note these
386  * calculations must agree with LockShmemSize!
387  */
388  max_table_size = NLOCKENTS();
389  init_table_size = max_table_size / 2;
390 
391  /*
392  * Allocate hash table for LOCK structs. This stores per-locked-object
393  * information.
394  */
395  MemSet(&info, 0, sizeof(info));
396  info.keysize = sizeof(LOCKTAG);
397  info.entrysize = sizeof(LOCK);
399 
400  LockMethodLockHash = ShmemInitHash("LOCK hash",
401  init_table_size,
402  max_table_size,
403  &info,
405 
406  /* Assume an average of 2 holders per lock */
407  max_table_size *= 2;
408  init_table_size *= 2;
409 
410  /*
411  * Allocate hash table for PROCLOCK structs. This stores
412  * per-lock-per-holder information.
413  */
414  info.keysize = sizeof(PROCLOCKTAG);
415  info.entrysize = sizeof(PROCLOCK);
416  info.hash = proclock_hash;
418 
419  LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
420  init_table_size,
421  max_table_size,
422  &info,
424 
425  /*
426  * Allocate fast-path structures.
427  */
429  ShmemInitStruct("Fast Path Strong Relation Lock Data",
430  sizeof(FastPathStrongRelationLockData), &found);
431  if (!found)
433 
434  /*
435  * Allocate non-shared hash table for LOCALLOCK structs. This stores lock
436  * counts and resource owner information.
437  *
438  * The non-shared table could already exist in this process (this occurs
439  * when the postmaster is recreating shared memory after a backend crash).
440  * If so, delete and recreate it. (We could simply leave it, since it
441  * ought to be empty in the postmaster, but for safety let's zap it.)
442  */
445 
446  info.keysize = sizeof(LOCALLOCKTAG);
447  info.entrysize = sizeof(LOCALLOCK);
448 
449  LockMethodLocalHash = hash_create("LOCALLOCK hash",
450  16,
451  &info,
453 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:814
static HTAB * LockMethodLocalHash
Definition: lock.c:255
#define HASH_ELEM
Definition: hsearch.h:87
#define SpinLockInit(lock)
Definition: spin.h:60
Size entrysize
Definition: hsearch.h:73
static uint32 proclock_hash(const void *key, Size keysize)
Definition: lock.c:507
#define MemSet(start, val, len)
Definition: c.h:941
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
struct LOCALLOCKTAG LOCALLOCKTAG
#define HASH_PARTITION
Definition: hsearch.h:83
#define NLOCKENTS()
Definition: lock.c:56
struct LOCALLOCK LOCALLOCK
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
long num_partitions
Definition: hsearch.h:67
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:372
struct PROCLOCK PROCLOCK
struct LOCKTAG LOCKTAG
#define HASH_BLOBS
Definition: hsearch.h:88
struct PROCLOCKTAG PROCLOCKTAG
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:316
Size keysize
Definition: hsearch.h:72
struct LOCK LOCK
static HTAB * LockMethodLockHash
Definition: lock.c:253
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:317
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
HashValueFunc hash
Definition: hsearch.h:74
#define HASH_FUNCTION
Definition: hsearch.h:89

◆ lock_twophase_postabort()

void lock_twophase_postabort ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4248 of file lock.c.

References lock_twophase_postcommit().

4250 {
4251  lock_twophase_postcommit(xid, info, recdata, len);
4252 }
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
Definition: lock.c:4222

◆ lock_twophase_postcommit()

void lock_twophase_postcommit ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4222 of file lock.c.

References Assert, elog, ERROR, lengthof, TwoPhaseLockRecord::lockmode, LockRefindAndRelease(), TwoPhaseLockRecord::locktag, LOCKTAG::locktag_lockmethodid, and TwoPhaseGetDummyProc().

Referenced by lock_twophase_postabort().

4224 {
4225  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4226  PGPROC *proc = TwoPhaseGetDummyProc(xid);
4227  LOCKTAG *locktag;
4228  LOCKMETHODID lockmethodid;
4229  LockMethod lockMethodTable;
4230 
4231  Assert(len == sizeof(TwoPhaseLockRecord));
4232  locktag = &rec->locktag;
4233  lockmethodid = locktag->locktag_lockmethodid;
4234 
4235  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4236  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4237  lockMethodTable = LockMethods[lockmethodid];
4238 
4239  LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4240 }
PGPROC * TwoPhaseGetDummyProc(TransactionId xid)
Definition: twophase.c:867
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3013
Definition: lock.h:178
#define lengthof(array)
Definition: c.h:662
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:732
uint8 locktag_lockmethodid
Definition: lock.h:185
#define elog(elevel,...)
Definition: elog.h:226
static const LockMethod LockMethods[]
Definition: lock.c:150
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:95

◆ lock_twophase_recover()

void lock_twophase_recover ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4009 of file lock.c.

References Assert, ConflictsWithRelationFastPath, FastPathStrongRelationLockData::count, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FastPathStrongLockHashPartition, LOCK::granted, GrantLock(), LOCK::grantMask, PROCLOCK::groupLeader, HASH_ENTER_NULL, HASH_REMOVE, hash_search_with_hash_value(), PROCLOCK::holdMask, lengthof, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartition, LockHashPartitionLock, PROCLOCK::lockLink, TwoPhaseLockRecord::lockmode, LockMethodData::lockModeNames, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_field3, LOCKTAG::locktag_lockmethodid, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MAX_LOCKMODES, MemSet, FastPathStrongRelationLockData::mutex, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCK::nRequested, PANIC, PROCLOCK::procLink, PROCLOCK_PRINT, ProcLockHashCode(), LOCK::procLocks, ProcQueueInit(), PROCLOCK::releaseMask, LOCK::requested, SHMQueueEmpty(), SHMQueueInit(), SHMQueueInsertBefore(), SpinLockAcquire, SpinLockRelease, LOCK::tag, TwoPhaseGetDummyProc(), LOCK::waitMask, and LOCK::waitProcs.

4011 {
4012  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4013  PGPROC *proc = TwoPhaseGetDummyProc(xid);
4014  LOCKTAG *locktag;
4015  LOCKMODE lockmode;
4016  LOCKMETHODID lockmethodid;
4017  LOCK *lock;
4018  PROCLOCK *proclock;
4019  PROCLOCKTAG proclocktag;
4020  bool found;
4021  uint32 hashcode;
4022  uint32 proclock_hashcode;
4023  int partition;
4024  LWLock *partitionLock;
4025  LockMethod lockMethodTable;
4026 
4027  Assert(len == sizeof(TwoPhaseLockRecord));
4028  locktag = &rec->locktag;
4029  lockmode = rec->lockmode;
4030  lockmethodid = locktag->locktag_lockmethodid;
4031 
4032  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4033  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4034  lockMethodTable = LockMethods[lockmethodid];
4035 
4036  hashcode = LockTagHashCode(locktag);
4037  partition = LockHashPartition(hashcode);
4038  partitionLock = LockHashPartitionLock(hashcode);
4039 
4040  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4041 
4042  /*
4043  * Find or create a lock with this tag.
4044  */
4046  (void *) locktag,
4047  hashcode,
4049  &found);
4050  if (!lock)
4051  {
4052  LWLockRelease(partitionLock);
4053  ereport(ERROR,
4054  (errcode(ERRCODE_OUT_OF_MEMORY),
4055  errmsg("out of shared memory"),
4056  errhint("You might need to increase max_locks_per_transaction.")));
4057  }
4058 
4059  /*
4060  * if it's a new lock object, initialize it
4061  */
4062  if (!found)
4063  {
4064  lock->grantMask = 0;
4065  lock->waitMask = 0;
4066  SHMQueueInit(&(lock->procLocks));
4067  ProcQueueInit(&(lock->waitProcs));
4068  lock->nRequested = 0;
4069  lock->nGranted = 0;
4070  MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4071  MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4072  LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4073  }
4074  else
4075  {
4076  LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4077  Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4078  Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4079  Assert(lock->nGranted <= lock->nRequested);
4080  }
4081 
4082  /*
4083  * Create the hash key for the proclock table.
4084  */
4085  proclocktag.myLock = lock;
4086  proclocktag.myProc = proc;
4087 
4088  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4089 
4090  /*
4091  * Find or create a proclock entry with this tag
4092  */
4094  (void *) &proclocktag,
4095  proclock_hashcode,
4097  &found);
4098  if (!proclock)
4099  {
4100  /* Oops, not enough shmem for the proclock */
4101  if (lock->nRequested == 0)
4102  {
4103  /*
4104  * There are no other requestors of this lock, so garbage-collect
4105  * the lock object. We *must* do this to avoid a permanent leak
4106  * of shared memory, because there won't be anything to cause
4107  * anyone to release the lock object later.
4108  */
4109  Assert(SHMQueueEmpty(&(lock->procLocks)));
4111  (void *) &(lock->tag),
4112  hashcode,
4113  HASH_REMOVE,
4114  NULL))
4115  elog(PANIC, "lock table corrupted");
4116  }
4117  LWLockRelease(partitionLock);
4118  ereport(ERROR,
4119  (errcode(ERRCODE_OUT_OF_MEMORY),
4120  errmsg("out of shared memory"),
4121  errhint("You might need to increase max_locks_per_transaction.")));
4122  }
4123 
4124  /*
4125  * If new, initialize the new entry
4126  */
4127  if (!found)
4128  {
4129  Assert(proc->lockGroupLeader == NULL);
4130  proclock->groupLeader = proc;
4131  proclock->holdMask = 0;
4132  proclock->releaseMask = 0;
4133  /* Add proclock to appropriate lists */
4134  SHMQueueInsertBefore(&lock->procLocks, &proclock->lockLink);
4135  SHMQueueInsertBefore(&(proc->myProcLocks[partition]),
4136  &proclock->procLink);
4137  PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4138  }
4139  else
4140  {
4141  PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4142  Assert((proclock->holdMask & ~lock->grantMask) == 0);
4143  }
4144 
4145  /*
4146  * lock->nRequested and lock->requested[] count the total number of
4147  * requests, whether granted or waiting, so increment those immediately.
4148  */
4149  lock->nRequested++;
4150  lock->requested[lockmode]++;
4151  Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4152 
4153  /*
4154  * We shouldn't already hold the desired lock.
4155  */
4156  if (proclock->holdMask & LOCKBIT_ON(lockmode))
4157  elog(ERROR, "lock %s on object %u/%u/%u is already held",
4158  lockMethodTable->lockModeNames[lockmode],
4159  lock->tag.locktag_field1, lock->tag.locktag_field2,
4160  lock->tag.locktag_field3);
4161 
4162  /*
4163  * We ignore any possible conflicts and just grant ourselves the lock. Not
4164  * only because we don't bother, but also to avoid deadlocks when
4165  * switching from standby to normal mode. See function comment.
4166  */
4167  GrantLock(lock, proclock, lockmode);
4168 
4169  /*
4170  * Bump strong lock count, to make sure any fast-path lock requests won't
4171  * be granted without consulting the primary lock table.
4172  */
4173  if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4174  {
4175  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4176 
4178  FastPathStrongRelationLocks->count[fasthashcode]++;
4180  }
4181 
4182  LWLockRelease(partitionLock);
4183 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
PGPROC * TwoPhaseGetDummyProc(TransactionId xid)
Definition: twophase.c:867
Definition: lwlock.h:32
int errhint(const char *fmt,...)
Definition: elog.c:987
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
int LOCKMODE
Definition: lockdefs.h:26
int nRequested
Definition: lock.h:295
LOCKMASK holdMask
Definition: lock.h:351
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1443
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
LOCKTAG tag
Definition: lock.h:287
Definition: lock.h:178
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
SHM_QUEUE lockLink
Definition: lock.h:353
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:941
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
#define LockHashPartition(hashcode)
Definition: lock.h:497
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:662
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:297
PROC_QUEUE waitProcs
Definition: lock.h:293
LOCKTAG locktag
Definition: lock.c:160
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
void ProcQueueInit(PROC_QUEUE *queue)
Definition: proc.c:1015
uint32 locktag_field2
Definition: lock.h:181
unsigned int uint32
Definition: c.h:358
int granted[MAX_LOCKMODES]
Definition: lock.h:296
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define ereport(elevel, rest)
Definition: elog.h:141
LOCKMASK waitMask
Definition: lock.h:291
uint16 LOCKMETHODID
Definition: lock.h:125
SHM_QUEUE procLocks
Definition: lock.h:292
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define SpinLockRelease(lock)
Definition: spin.h:64
int requested[MAX_LOCKMODES]
Definition: lock.h:294
#define MAX_LOCKMODES
Definition: lock.h:85
SHM_QUEUE procLink
Definition: lock.h:354
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:732
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290
Definition: lock.h:344
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
#define elog(elevel,...)
Definition: elog.h:226
LOCK * myLock
Definition: lock.h:340
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
uint32 locktag_field1
Definition: lock.h:180
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:95
uint32 locktag_field3
Definition: lock.h:182
PGPROC * lockGroupLeader
Definition: proc.h:203
const char *const * lockModeNames
Definition: lock.h:115
PGPROC * groupLeader
Definition: lock.h:350
LOCKMASK releaseMask
Definition: lock.h:352

◆ lock_twophase_standby_recover()

void lock_twophase_standby_recover ( TransactionId  xid,
uint16  info,
void *  recdata,
uint32  len 
)

Definition at line 4190 of file lock.c.

References AccessExclusiveLock, Assert, elog, ERROR, lengthof, TwoPhaseLockRecord::lockmode, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOCKTAG_RELATION, LOCKTAG::locktag_type, and StandbyAcquireAccessExclusiveLock().

4192 {
4193  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4194  LOCKTAG *locktag;
4195  LOCKMODE lockmode;
4196  LOCKMETHODID lockmethodid;
4197 
4198  Assert(len == sizeof(TwoPhaseLockRecord));
4199  locktag = &rec->locktag;
4200  lockmode = rec->lockmode;
4201  lockmethodid = locktag->locktag_lockmethodid;
4202 
4203  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4204  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4205 
4206  if (lockmode == AccessExclusiveLock &&
4207  locktag->locktag_type == LOCKTAG_RELATION)
4208  {
4210  locktag->locktag_field1 /* dboid */ ,
4211  locktag->locktag_field2 /* reloid */ );
4212  }
4213 }
int LOCKMODE
Definition: lockdefs.h:26
Definition: lock.h:178
#define lengthof(array)
Definition: c.h:662
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
uint32 locktag_field2
Definition: lock.h:181
uint16 LOCKMETHODID
Definition: lock.h:125
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:732
uint8 locktag_lockmethodid
Definition: lock.h:185
#define AccessExclusiveLock
Definition: lockdefs.h:45
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:629
#define elog(elevel,...)
Definition: elog.h:226
static const LockMethod LockMethods[]
Definition: lock.c:150
uint32 locktag_field1
Definition: lock.h:180
LOCKMODE lockmode
Definition: lock.c:161

◆ LockAcquire()

◆ LockAcquireExtended()

LockAcquireResult LockAcquireExtended ( const LOCKTAG locktag,
LOCKMODE  lockmode,
bool  sessionLock,
bool  dontWait,
bool  reportMemoryError,
LOCALLOCK **  locallockp 
)

Definition at line 708 of file lock.c.

References AbortStrongLockAcquire(), AccessExclusiveLock, Assert, PGPROC::backendLock, BeginStrongLockAcquire(), ConflictsWithRelationFastPath, LockMethodData::conflictTab, FastPathStrongRelationLockData::count, CurrentResourceOwner, EligibleForRelationFastPath, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FastPathGrantRelationLock(), FastPathLocalUseCount, FastPathStrongLockHashPartition, FastPathTransferRelationLocks(), FinishStrongLockAcquire(), FP_LOCK_SLOTS_PER_BACKEND, GrantLock(), GrantLockLocal(), HASH_ENTER, HASH_REMOVE, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, LOCALLOCK::holdsStrongLockCount, InRecovery, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKACQUIRE_ALREADY_CLEAR, LOCKACQUIRE_ALREADY_HELD, LOCKACQUIRE_NOT_AVAIL, LOCKACQUIRE_OK, LOCKBIT_ON, LockCheckConflicts(), LOCALLOCK::lockCleared, LockHashPartitionLock, PROCLOCK::lockLink, TwoPhaseLockRecord::lockmode, LockMethodData::lockModeNames, LOCALLOCK::lockOwners, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_field3, LOCKTAG::locktag_field4, LOCKTAG::locktag_lockmethodid, LOCKTAG_OBJECT, LOCKTAG_RELATION, LOCKTAG::locktag_type, LockTagHashCode(), LOG, LogAccessExclusiveLock(), LogAccessExclusiveLockPrepare(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LOCALLOCK::maxLockOwners, MemoryContextAlloc(), MemSet, LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, LOCK::nGranted, LOCALLOCK::nLocks, LOCK::nRequested, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, ProcLockHashCode(), RecoveryInProgress(), RemoveLocalLock(), repalloc(), LOCK::requested, RowExclusiveLock, SetupLockInTable(), SHMQueueDelete(), status(), STATUS_FOUND, STATUS_OK, PROCLOCK::tag, TopMemoryContext, LOCK::waitMask, WaitOnLock(), and XLogStandbyInfoActive.

Referenced by ConditionalLockRelation(), ConditionalLockRelationOid(), LockAcquire(), LockRelation(), and LockRelationOid().

714 {
715  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
716  LockMethod lockMethodTable;
717  LOCALLOCKTAG localtag;
718  LOCALLOCK *locallock;
719  LOCK *lock;
720  PROCLOCK *proclock;
721  bool found;
722  ResourceOwner owner;
723  uint32 hashcode;
724  LWLock *partitionLock;
725  int status;
726  bool log_lock = false;
727 
728  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
729  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
730  lockMethodTable = LockMethods[lockmethodid];
731  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
732  elog(ERROR, "unrecognized lock mode: %d", lockmode);
733 
734  if (RecoveryInProgress() && !InRecovery &&
735  (locktag->locktag_type == LOCKTAG_OBJECT ||
736  locktag->locktag_type == LOCKTAG_RELATION) &&
737  lockmode > RowExclusiveLock)
738  ereport(ERROR,
739  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
740  errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
741  lockMethodTable->lockModeNames[lockmode]),
742  errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
743 
744 #ifdef LOCK_DEBUG
745  if (LOCK_DEBUG_ENABLED(locktag))
746  elog(LOG, "LockAcquire: lock [%u,%u] %s",
747  locktag->locktag_field1, locktag->locktag_field2,
748  lockMethodTable->lockModeNames[lockmode]);
749 #endif
750 
751  /* Identify owner for lock */
752  if (sessionLock)
753  owner = NULL;
754  else
755  owner = CurrentResourceOwner;
756 
757  /*
758  * Find or create a LOCALLOCK entry for this lock and lockmode
759  */
760  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
761  localtag.lock = *locktag;
762  localtag.mode = lockmode;
763 
764  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
765  (void *) &localtag,
766  HASH_ENTER, &found);
767 
768  /*
769  * if it's a new locallock object, initialize it
770  */
771  if (!found)
772  {
773  locallock->lock = NULL;
774  locallock->proclock = NULL;
775  locallock->hashcode = LockTagHashCode(&(localtag.lock));
776  locallock->nLocks = 0;
777  locallock->holdsStrongLockCount = false;
778  locallock->lockCleared = false;
779  locallock->numLockOwners = 0;
780  locallock->maxLockOwners = 8;
781  locallock->lockOwners = NULL; /* in case next line fails */
782  locallock->lockOwners = (LOCALLOCKOWNER *)
784  locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
785  }
786  else
787  {
788  /* Make sure there will be room to remember the lock */
789  if (locallock->numLockOwners >= locallock->maxLockOwners)
790  {
791  int newsize = locallock->maxLockOwners * 2;
792 
793  locallock->lockOwners = (LOCALLOCKOWNER *)
794  repalloc(locallock->lockOwners,
795  newsize * sizeof(LOCALLOCKOWNER));
796  locallock->maxLockOwners = newsize;
797  }
798  }
799  hashcode = locallock->hashcode;
800 
801  if (locallockp)
802  *locallockp = locallock;
803 
804  /*
805  * If we already hold the lock, we can just increase the count locally.
806  *
807  * If lockCleared is already set, caller need not worry about absorbing
808  * sinval messages related to the lock's object.
809  */
810  if (locallock->nLocks > 0)
811  {
812  GrantLockLocal(locallock, owner);
813  if (locallock->lockCleared)
815  else
817  }
818 
819  /*
820  * Prepare to emit a WAL record if acquisition of this lock needs to be
821  * replayed in a standby server.
822  *
823  * Here we prepare to log; after lock is acquired we'll issue log record.
824  * This arrangement simplifies error recovery in case the preparation step
825  * fails.
826  *
827  * Only AccessExclusiveLocks can conflict with lock types that read-only
828  * transactions can acquire in a standby server. Make sure this definition
829  * matches the one in GetRunningTransactionLocks().
830  */
831  if (lockmode >= AccessExclusiveLock &&
832  locktag->locktag_type == LOCKTAG_RELATION &&
833  !RecoveryInProgress() &&
835  {
837  log_lock = true;
838  }
839 
840  /*
841  * Attempt to take lock via fast path, if eligible. But if we remember
842  * having filled up the fast path array, we don't attempt to make any
843  * further use of it until we release some locks. It's possible that some
844  * other backend has transferred some of those locks to the shared hash
845  * table, leaving space free, but it's not worth acquiring the LWLock just
846  * to check. It's also possible that we're acquiring a second or third
847  * lock type on a relation we have already locked using the fast-path, but
848  * for now we don't worry about that case either.
849  */
850  if (EligibleForRelationFastPath(locktag, lockmode) &&
852  {
853  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
854  bool acquired;
855 
856  /*
857  * LWLockAcquire acts as a memory sequencing point, so it's safe to
858  * assume that any strong locker whose increment to
859  * FastPathStrongRelationLocks->counts becomes visible after we test
860  * it has yet to begin to transfer fast-path locks.
861  */
863  if (FastPathStrongRelationLocks->count[fasthashcode] != 0)
864  acquired = false;
865  else
866  acquired = FastPathGrantRelationLock(locktag->locktag_field2,
867  lockmode);
869  if (acquired)
870  {
871  /*
872  * The locallock might contain stale pointers to some old shared
873  * objects; we MUST reset these to null before considering the
874  * lock to be acquired via fast-path.
875  */
876  locallock->lock = NULL;
877  locallock->proclock = NULL;
878  GrantLockLocal(locallock, owner);
879  return LOCKACQUIRE_OK;
880  }
881  }
882 
883  /*
884  * If this lock could potentially have been taken via the fast-path by
885  * some other backend, we must (temporarily) disable further use of the
886  * fast-path for this lock tag, and migrate any locks already taken via
887  * this method to the main lock table.
888  */
889  if (ConflictsWithRelationFastPath(locktag, lockmode))
890  {
891  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
892 
893  BeginStrongLockAcquire(locallock, fasthashcode);
894  if (!FastPathTransferRelationLocks(lockMethodTable, locktag,
895  hashcode))
896  {
898  if (locallock->nLocks == 0)
899  RemoveLocalLock(locallock);
900  if (locallockp)
901  *locallockp = NULL;
902  if (reportMemoryError)
903  ereport(ERROR,
904  (errcode(ERRCODE_OUT_OF_MEMORY),
905  errmsg("out of shared memory"),
906  errhint("You might need to increase max_locks_per_transaction.")));
907  else
908  return LOCKACQUIRE_NOT_AVAIL;
909  }
910  }
911 
912  /*
913  * We didn't find the lock in our LOCALLOCK table, and we didn't manage to
914  * take it via the fast-path, either, so we've got to mess with the shared
915  * lock table.
916  */
917  partitionLock = LockHashPartitionLock(hashcode);
918 
919  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
920 
921  /*
922  * Find or create lock and proclock entries with this tag
923  *
924  * Note: if the locallock object already existed, it might have a pointer
925  * to the lock already ... but we should not assume that that pointer is
926  * valid, since a lock object with zero hold and request counts can go
927  * away anytime. So we have to use SetupLockInTable() to recompute the
928  * lock and proclock pointers, even if they're already set.
929  */
930  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
931  hashcode, lockmode);
932  if (!proclock)
933  {
935  LWLockRelease(partitionLock);
936  if (locallock->nLocks == 0)
937  RemoveLocalLock(locallock);
938  if (locallockp)
939  *locallockp = NULL;
940  if (reportMemoryError)
941  ereport(ERROR,
942  (errcode(ERRCODE_OUT_OF_MEMORY),
943  errmsg("out of shared memory"),
944  errhint("You might need to increase max_locks_per_transaction.")));
945  else
946  return LOCKACQUIRE_NOT_AVAIL;
947  }
948  locallock->proclock = proclock;
949  lock = proclock->tag.myLock;
950  locallock->lock = lock;
951 
952  /*
953  * If lock requested conflicts with locks requested by waiters, must join
954  * wait queue. Otherwise, check for conflict with already-held locks.
955  * (That's last because most complex check.)
956  */
957  if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
958  status = STATUS_FOUND;
959  else
960  status = LockCheckConflicts(lockMethodTable, lockmode,
961  lock, proclock);
962 
963  if (status == STATUS_OK)
964  {
965  /* No conflict with held or previously requested locks */
966  GrantLock(lock, proclock, lockmode);
967  GrantLockLocal(locallock, owner);
968  }
969  else
970  {
971  Assert(status == STATUS_FOUND);
972 
973  /*
974  * We can't acquire the lock immediately. If caller specified no
975  * blocking, remove useless table entries and return NOT_AVAIL without
976  * waiting.
977  */
978  if (dontWait)
979  {
981  if (proclock->holdMask == 0)
982  {
983  uint32 proclock_hashcode;
984 
985  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
986  SHMQueueDelete(&proclock->lockLink);
987  SHMQueueDelete(&proclock->procLink);
989  (void *) &(proclock->tag),
990  proclock_hashcode,
991  HASH_REMOVE,
992  NULL))
993  elog(PANIC, "proclock table corrupted");
994  }
995  else
996  PROCLOCK_PRINT("LockAcquire: NOWAIT", proclock);
997  lock->nRequested--;
998  lock->requested[lockmode]--;
999  LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
1000  Assert((lock->nRequested > 0) && (lock->requested[lockmode] >= 0));
1001  Assert(lock->nGranted <= lock->nRequested);
1002  LWLockRelease(partitionLock);
1003  if (locallock->nLocks == 0)
1004  RemoveLocalLock(locallock);
1005  if (locallockp)
1006  *locallockp = NULL;
1007  return LOCKACQUIRE_NOT_AVAIL;
1008  }
1009 
1010  /*
1011  * Set bitmask of locks this process already holds on this object.
1012  */
1013  MyProc->heldLocks = proclock->holdMask;
1014 
1015  /*
1016  * Sleep till someone wakes me up.
1017  */
1018 
1019  TRACE_POSTGRESQL_LOCK_WAIT_START(locktag->locktag_field1,
1020  locktag->locktag_field2,
1021  locktag->locktag_field3,
1022  locktag->locktag_field4,
1023  locktag->locktag_type,
1024  lockmode);
1025 
1026  WaitOnLock(locallock, owner);
1027 
1028  TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
1029  locktag->locktag_field2,
1030  locktag->locktag_field3,
1031  locktag->locktag_field4,
1032  locktag->locktag_type,
1033  lockmode);
1034 
1035  /*
1036  * NOTE: do not do any material change of state between here and
1037  * return. All required changes in locktable state must have been
1038  * done when the lock was granted to us --- see notes in WaitOnLock.
1039  */
1040 
1041  /*
1042  * Check the proclock entry status, in case something in the ipc
1043  * communication doesn't work correctly.
1044  */
1045  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
1046  {
1048  PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
1049  LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
1050  /* Should we retry ? */
1051  LWLockRelease(partitionLock);
1052  elog(ERROR, "LockAcquire failed");
1053  }
1054  PROCLOCK_PRINT("LockAcquire: granted", proclock);
1055  LOCK_PRINT("LockAcquire: granted", lock, lockmode);
1056  }
1057 
1058  /*
1059  * Lock state is fully up-to-date now; if we error out after this, no
1060  * special error cleanup is required.
1061  */
1063 
1064  LWLockRelease(partitionLock);
1065 
1066  /*
1067  * Emit a WAL record if acquisition of this lock needs to be replayed in a
1068  * standby server.
1069  */
1070  if (log_lock)
1071  {
1072  /*
1073  * Decode the locktag back to the original values, to avoid sending
1074  * lots of empty bytes with every message. See lock.h to check how a
1075  * locktag is defined for LOCKTAG_RELATION
1076  */
1078  locktag->locktag_field2);
1079  }
1080 
1081  return LOCKACQUIRE_OK;
1082 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
PROCLOCKTAG tag
Definition: lock.h:347
uint32 hashcode
Definition: lock.h:409
Definition: lwlock.h:32
int LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1320
static HTAB * LockMethodLocalHash
Definition: lock.c:255
bool holdsStrongLockCount
Definition: lock.h:411
int errhint(const char *fmt,...)
Definition: elog.c:987
int numLockOwners
Definition: lock.h:413
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1095
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
LOCKTAG lock
Definition: lock.h:385
static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2540
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
int nRequested
Definition: lock.h:295
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1443
ResourceOwner CurrentResourceOwner
Definition: resowner.c:141
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
bool InRecovery
Definition: xlog.c:194
static int FastPathLocalUseCount
Definition: lock.c:171
const LOCKMASK * conflictTab
Definition: lock.h:114
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
SHM_QUEUE lockLink
Definition: lock.h:353
void LogAccessExclusiveLock(Oid dbOid, Oid relOid)
Definition: standby.c:1039
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:941
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:662
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:8082
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:199
#define PANIC
Definition: elog.h:53
int maxLockOwners
Definition: lock.h:414
int nGranted
Definition: lock.h:297
static void WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1699
uint16 locktag_field4
Definition: lock.h:183
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define ERROR
Definition: elog.h:43
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1272
static void FinishStrongLockAcquire(void)
Definition: lock.c:1632
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
#define RowExclusiveLock
Definition: lockdefs.h:38
void LogAccessExclusiveLockPrepare(void)
Definition: standby.c:1056
void AbortStrongLockAcquire(void)
Definition: lock.c:1642
uint32 locktag_field2
Definition: lock.h:181
unsigned int uint32
Definition: c.h:358
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define ereport(elevel, rest)
Definition: elog.h:141
#define STATUS_OK
Definition: c.h:1067
MemoryContext TopMemoryContext
Definition: mcxt.c:44
LOCKMASK waitMask
Definition: lock.h:291
uint16 LOCKMETHODID
Definition: lock.h:125
int requested[MAX_LOCKMODES]
Definition: lock.h:294
SHM_QUEUE procLink
Definition: lock.h:354
static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode)
Definition: lock.c:1606
#define XLogStandbyInfoActive()
Definition: xlog.h:160
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:732
#define STATUS_FOUND
Definition: c.h:1070
LWLock backendLock
Definition: proc.h:190
LOCALLOCKOWNER * lockOwners
Definition: lock.h:415
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
LOCK * lock
Definition: lock.h:407
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
uint8 locktag_lockmethodid
Definition: lock.h:185
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
int errmsg(const char *fmt,...)
Definition: elog.c:797
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
#define elog(elevel,...)
Definition: elog.h:226
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
LOCK * myLock
Definition: lock.h:340
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static bool FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag, uint32 hashcode)
Definition: lock.c:2607
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
uint32 locktag_field1
Definition: lock.h:180
uint32 locktag_field3
Definition: lock.h:182
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1577
bool lockCleared
Definition: lock.h:412
const char *const * lockModeNames
Definition: lock.h:115
LOCKMASK heldLocks
Definition: proc.h:142
int numLockModes
Definition: lock.h:113

◆ LockCheckConflicts()

int LockCheckConflicts ( LockMethod  lockMethodTable,
LOCKMODE  lockmode,
LOCK lock,
PROCLOCK proclock 
)

Definition at line 1320 of file lock.c.

References Assert, LockMethodData::conflictTab, elog, LOCK::granted, LOCK::grantMask, PROCLOCK::groupLeader, PROCLOCK::holdMask, i, LOCKBIT_ON, PGPROC::lockGroupLeader, PROCLOCK::lockLink, TwoPhaseLockRecord::lockmode, MAX_LOCKMODES, MyProc, PROCLOCKTAG::myProc, LockMethodData::numLockModes, offsetof, PANIC, PROCLOCK_PRINT, LOCK::procLocks, SHMQueueNext(), STATUS_FOUND, STATUS_OK, and PROCLOCK::tag.

Referenced by LockAcquireExtended(), ProcLockWakeup(), and ProcSleep().

1324 {
1325  int numLockModes = lockMethodTable->numLockModes;
1326  LOCKMASK myLocks;
1327  int conflictMask = lockMethodTable->conflictTab[lockmode];
1328  int conflictsRemaining[MAX_LOCKMODES];
1329  int totalConflictsRemaining = 0;
1330  int i;
1331  SHM_QUEUE *procLocks;
1332  PROCLOCK *otherproclock;
1333 
1334  /*
1335  * first check for global conflicts: If no locks conflict with my request,
1336  * then I get the lock.
1337  *
1338  * Checking for conflict: lock->grantMask represents the types of
1339  * currently held locks. conflictTable[lockmode] has a bit set for each
1340  * type of lock that conflicts with request. Bitwise compare tells if
1341  * there is a conflict.
1342  */
1343  if (!(conflictMask & lock->grantMask))
1344  {
1345  PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1346  return STATUS_OK;
1347  }
1348 
1349  /*
1350  * Rats. Something conflicts. But it could still be my own lock, or a
1351  * lock held by another member of my locking group. First, figure out how
1352  * many conflicts remain after subtracting out any locks I hold myself.
1353  */
1354  myLocks = proclock->holdMask;
1355  for (i = 1; i <= numLockModes; i++)
1356  {
1357  if ((conflictMask & LOCKBIT_ON(i)) == 0)
1358  {
1359  conflictsRemaining[i] = 0;
1360  continue;
1361  }
1362  conflictsRemaining[i] = lock->granted[i];
1363  if (myLocks & LOCKBIT_ON(i))
1364  --conflictsRemaining[i];
1365  totalConflictsRemaining += conflictsRemaining[i];
1366  }
1367 
1368  /* If no conflicts remain, we get the lock. */
1369  if (totalConflictsRemaining == 0)
1370  {
1371  PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1372  return STATUS_OK;
1373  }
1374 
1375  /* If no group locking, it's definitely a conflict. */
1376  if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL)
1377  {
1378  Assert(proclock->tag.myProc == MyProc);
1379  PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1380  proclock);
1381  return STATUS_FOUND;
1382  }
1383 
1384  /*
1385  * Locks held in conflicting modes by members of our own lock group are
1386  * not real conflicts; we can subtract those out and see if we still have
1387  * a conflict. This is O(N) in the number of processes holding or
1388  * awaiting locks on this object. We could improve that by making the
1389  * shared memory state more complex (and larger) but it doesn't seem worth
1390  * it.
1391  */
1392  procLocks = &(lock->procLocks);
1393  otherproclock = (PROCLOCK *)
1394  SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink));
1395  while (otherproclock != NULL)
1396  {
1397  if (proclock != otherproclock &&
1398  proclock->groupLeader == otherproclock->groupLeader &&
1399  (otherproclock->holdMask & conflictMask) != 0)
1400  {
1401  int intersectMask = otherproclock->holdMask & conflictMask;
1402 
1403  for (i = 1; i <= numLockModes; i++)
1404  {
1405  if ((intersectMask & LOCKBIT_ON(i)) != 0)
1406  {
1407  if (conflictsRemaining[i] <= 0)
1408  elog(PANIC, "proclocks held do not match lock");
1409  conflictsRemaining[i]--;
1410  totalConflictsRemaining--;
1411  }
1412  }
1413 
1414  if (totalConflictsRemaining == 0)
1415  {
1416  PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1417  proclock);
1418  return STATUS_OK;
1419  }
1420  }
1421  otherproclock = (PROCLOCK *)
1422  SHMQueueNext(procLocks, &otherproclock->lockLink,
1423  offsetof(PROCLOCK, lockLink));
1424  }
1425 
1426  /* Nope, it's a real conflict. */
1427  PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1428  return STATUS_FOUND;
1429 }
PROCLOCKTAG tag
Definition: lock.h:347
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
const LOCKMASK * conflictTab
Definition: lock.h:114
SHM_QUEUE lockLink
Definition: lock.h:353
#define PANIC
Definition: elog.h:53
int granted[MAX_LOCKMODES]
Definition: lock.h:296
#define STATUS_OK
Definition: c.h:1067
SHM_QUEUE procLocks
Definition: lock.h:292
#define MAX_LOCKMODES
Definition: lock.h:85
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:732
#define STATUS_FOUND
Definition: c.h:1070
int LOCKMASK
Definition: lockdefs.h:25
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290
Definition: lock.h:344
#define elog(elevel,...)
Definition: elog.h:226
int i
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
PGPROC * lockGroupLeader
Definition: proc.h:203
#define offsetof(type, field)
Definition: c.h:655
PGPROC * groupLeader
Definition: lock.h:350
int numLockModes
Definition: lock.h:113

◆ LockHasWaiters()

bool LockHasWaiters ( const LOCKTAG locktag,
LOCKMODE  lockmode,
bool  sessionLock 
)

Definition at line 571 of file lock.c.

References LockMethodData::conflictTab, elog, ERROR, HASH_FIND, hash_search(), LOCALLOCK::hashcode, PROCLOCK::holdMask, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLock, TwoPhaseLockRecord::lockmode, LockMethodData::lockModeNames, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOG, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, LOCALLOCKTAG::mode, LOCALLOCK::nLocks, LockMethodData::numLockModes, LOCALLOCK::proclock, PROCLOCK_PRINT, RemoveLocalLock(), LOCK::waitMask, and WARNING.

Referenced by LockHasWaitersRelation().

572 {
573  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
574  LockMethod lockMethodTable;
575  LOCALLOCKTAG localtag;
576  LOCALLOCK *locallock;
577  LOCK *lock;
578  PROCLOCK *proclock;
579  LWLock *partitionLock;
580  bool hasWaiters = false;
581 
582  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
583  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
584  lockMethodTable = LockMethods[lockmethodid];
585  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
586  elog(ERROR, "unrecognized lock mode: %d", lockmode);
587 
588 #ifdef LOCK_DEBUG
589  if (LOCK_DEBUG_ENABLED(locktag))
590  elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
591  locktag->locktag_field1, locktag->locktag_field2,
592  lockMethodTable->lockModeNames[lockmode]);
593 #endif
594 
595  /*
596  * Find the LOCALLOCK entry for this lock and lockmode
597  */
598  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
599  localtag.lock = *locktag;
600  localtag.mode = lockmode;
601 
602  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
603  (void *) &localtag,
604  HASH_FIND, NULL);
605 
606  /*
607  * let the caller print its own error message, too. Do not ereport(ERROR).
608  */
609  if (!locallock || locallock->nLocks <= 0)
610  {
611  elog(WARNING, "you don't own a lock of type %s",
612  lockMethodTable->lockModeNames[lockmode]);
613  return false;
614  }
615 
616  /*
617  * Check the shared lock table.
618  */
619  partitionLock = LockHashPartitionLock(locallock->hashcode);
620 
621  LWLockAcquire(partitionLock, LW_SHARED);
622 
623  /*
624  * We don't need to re-find the lock or proclock, since we kept their
625  * addresses in the locallock table, and they couldn't have been removed
626  * while we were holding a lock on them.
627  */
628  lock = locallock->lock;
629  LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
630  proclock = locallock->proclock;
631  PROCLOCK_PRINT("LockHasWaiters: found", proclock);
632 
633  /*
634  * Double-check that we are actually holding a lock of the type we want to
635  * release.
636  */
637  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
638  {
639  PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
640  LWLockRelease(partitionLock);
641  elog(WARNING, "you don't own a lock of type %s",
642  lockMethodTable->lockModeNames[lockmode]);
643  RemoveLocalLock(locallock);
644  return false;
645  }
646 
647  /*
648  * Do the checking.
649  */
650  if ((lockMethodTable->conflictTab[lockmode] & lock->waitMask) != 0)
651  hasWaiters = true;
652 
653  LWLockRelease(partitionLock);
654 
655  return hasWaiters;
656 }
uint32 hashcode
Definition: lock.h:409
Definition: lwlock.h:32
static HTAB * LockMethodLocalHash
Definition: lock.c:255
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
LOCKMASK holdMask
Definition: lock.h:351
const LOCKMASK * conflictTab
Definition: lock.h:114
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
#define MemSet(start, val, len)
Definition: c.h:941
#define lengthof(array)
Definition: c.h:662
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1272
uint32 locktag_field2
Definition: lock.h:181
Definition: lock.h:284
LOCKMASK waitMask
Definition: lock.h:291
uint16 LOCKMETHODID
Definition: lock.h:125
#define WARNING
Definition: elog.h:40
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
LOCK * lock
Definition: lock.h:407
uint8 locktag_lockmethodid
Definition: lock.h:185
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
#define elog(elevel,...)
Definition: elog.h:226
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
uint32 locktag_field1
Definition: lock.h:180
const char *const * lockModeNames
Definition: lock.h:115
int numLockModes
Definition: lock.h:113

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2464 of file lock.c.

References Assert, CurrentResourceOwner, hash_seq_init(), hash_seq_search(), i, LockReassignOwner(), ResourceOwnerGetParent(), and status().

Referenced by ResourceOwnerReleaseInternal().

2465 {
2467 
2468  Assert(parent != NULL);
2469 
2470  if (locallocks == NULL)
2471  {
2473  LOCALLOCK *locallock;
2474 
2476 
2477  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2478  LockReassignOwner(locallock, parent);
2479  }
2480  else
2481  {
2482  int i;
2483 
2484  for (i = nlocks - 1; i >= 0; i--)
2485  LockReassignOwner(locallocks[i], parent);
2486  }
2487 }
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2494
static HTAB * LockMethodLocalHash
Definition: lock.c:255
ResourceOwner CurrentResourceOwner
Definition: resowner.c:141
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition: resowner.c:738
#define Assert(condition)
Definition: c.h:732
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ LockRelease()

bool LockRelease ( const LOCKTAG locktag,
LOCKMODE  lockmode,
bool  sessionLock 
)

Definition at line 1860 of file lock.c.

References Assert, PGPROC::backendLock, CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FastPathLocalUseCount, FastPathUnGrantRelationLock(), HASH_FIND, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PROCLOCK::holdMask, i, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, LOCALLOCK::lockCleared, LockHashPartitionLock, TwoPhaseLockRecord::lockmode, LockMethodData::lockModeNames, LOCALLOCK::lockOwners, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, LOCALLOCK::nLocks, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, LOCALLOCK::proclock, PROCLOCK_PRINT, RemoveLocalLock(), ResourceOwnerForgetLock(), UnGrantLock(), and WARNING.

Referenced by ConditionalXactLockTableWait(), pg_advisory_unlock_int4(), pg_advisory_unlock_int8(), pg_advisory_unlock_shared_int4(), pg_advisory_unlock_shared_int8(), ReleaseLockIfHeld(), SpeculativeInsertionLockRelease(), SpeculativeInsertionWait(), StandbyReleaseLockList(), UnlockDatabaseObject(), UnlockPage(), UnlockRelation(), UnlockRelationForExtension(), UnlockRelationId(), UnlockRelationIdForSession(), UnlockRelationOid(), UnlockSharedObject(), UnlockSharedObjectForSession(), UnlockTuple(), VirtualXactLock(), XactLockTableDelete(), and XactLockTableWait().

1861 {
1862  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
1863  LockMethod lockMethodTable;
1864  LOCALLOCKTAG localtag;
1865  LOCALLOCK *locallock;
1866  LOCK *lock;
1867  PROCLOCK *proclock;
1868  LWLock *partitionLock;
1869  bool wakeupNeeded;
1870 
1871  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
1872  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
1873  lockMethodTable = LockMethods[lockmethodid];
1874  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
1875  elog(ERROR, "unrecognized lock mode: %d", lockmode);
1876 
1877 #ifdef LOCK_DEBUG
1878  if (LOCK_DEBUG_ENABLED(locktag))
1879  elog(LOG, "LockRelease: lock [%u,%u] %s",
1880  locktag->locktag_field1, locktag->locktag_field2,
1881  lockMethodTable->lockModeNames[lockmode]);
1882 #endif
1883 
1884  /*
1885  * Find the LOCALLOCK entry for this lock and lockmode
1886  */
1887  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
1888  localtag.lock = *locktag;
1889  localtag.mode = lockmode;
1890 
1891  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
1892  (void *) &localtag,
1893  HASH_FIND, NULL);
1894 
1895  /*
1896  * let the caller print its own error message, too. Do not ereport(ERROR).
1897  */
1898  if (!locallock || locallock->nLocks <= 0)
1899  {
1900  elog(WARNING, "you don't own a lock of type %s",
1901  lockMethodTable->lockModeNames[lockmode]);
1902  return false;
1903  }
1904 
1905  /*
1906  * Decrease the count for the resource owner.
1907  */
1908  {
1909  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1910  ResourceOwner owner;
1911  int i;
1912 
1913  /* Identify owner for lock */
1914  if (sessionLock)
1915  owner = NULL;
1916  else
1917  owner = CurrentResourceOwner;
1918 
1919  for (i = locallock->numLockOwners - 1; i >= 0; i--)
1920  {
1921  if (lockOwners[i].owner == owner)
1922  {
1923  Assert(lockOwners[i].nLocks > 0);
1924  if (--lockOwners[i].nLocks == 0)
1925  {
1926  if (owner != NULL)
1927  ResourceOwnerForgetLock(owner, locallock);
1928  /* compact out unused slot */
1929  locallock->numLockOwners--;
1930  if (i < locallock->numLockOwners)
1931  lockOwners[i] = lockOwners[locallock->numLockOwners];
1932  }
1933  break;
1934  }
1935  }
1936  if (i < 0)
1937  {
1938  /* don't release a lock belonging to another owner */
1939  elog(WARNING, "you don't own a lock of type %s",
1940  lockMethodTable->lockModeNames[lockmode]);
1941  return false;
1942  }
1943  }
1944 
1945  /*
1946  * Decrease the total local count. If we're still holding the lock, we're
1947  * done.
1948  */
1949  locallock->nLocks--;
1950 
1951  if (locallock->nLocks > 0)
1952  return true;
1953 
1954  /*
1955  * At this point we can no longer suppose we are clear of invalidation
1956  * messages related to this lock. Although we'll delete the LOCALLOCK
1957  * object before any intentional return from this routine, it seems worth
1958  * the trouble to explicitly reset lockCleared right now, just in case
1959  * some error prevents us from deleting the LOCALLOCK.
1960  */
1961  locallock->lockCleared = false;
1962 
1963  /* Attempt fast release of any lock eligible for the fast path. */
1964  if (EligibleForRelationFastPath(locktag, lockmode) &&
1966  {
1967  bool released;
1968 
1969  /*
1970  * We might not find the lock here, even if we originally entered it
1971  * here. Another backend may have moved it to the main table.
1972  */
1974  released = FastPathUnGrantRelationLock(locktag->locktag_field2,
1975  lockmode);
1977  if (released)
1978  {
1979  RemoveLocalLock(locallock);
1980  return true;
1981  }
1982  }
1983 
1984  /*
1985  * Otherwise we've got to mess with the shared lock table.
1986  */
1987  partitionLock = LockHashPartitionLock(locallock->hashcode);
1988 
1989  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
1990 
1991  /*
1992  * Normally, we don't need to re-find the lock or proclock, since we kept
1993  * their addresses in the locallock table, and they couldn't have been
1994  * removed while we were holding a lock on them. But it's possible that
1995  * the lock was taken fast-path and has since been moved to the main hash
1996  * table by another backend, in which case we will need to look up the
1997  * objects here. We assume the lock field is NULL if so.
1998  */
1999  lock = locallock->lock;
2000  if (!lock)
2001  {
2002  PROCLOCKTAG proclocktag;
2003 
2004  Assert(EligibleForRelationFastPath(locktag, lockmode));
2006  (const void *) locktag,
2007  locallock->hashcode,
2008  HASH_FIND,
2009  NULL);
2010  if (!lock)
2011  elog(ERROR, "failed to re-find shared lock object");
2012  locallock->lock = lock;
2013 
2014  proclocktag.myLock = lock;
2015  proclocktag.myProc = MyProc;
2017  (void *) &proclocktag,
2018  HASH_FIND,
2019  NULL);
2020  if (!locallock->proclock)
2021  elog(ERROR, "failed to re-find shared proclock object");
2022  }
2023  LOCK_PRINT("LockRelease: found", lock, lockmode);
2024  proclock = locallock->proclock;
2025  PROCLOCK_PRINT("LockRelease: found", proclock);
2026 
2027  /*
2028  * Double-check that we are actually holding a lock of the type we want to
2029  * release.
2030  */
2031  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2032  {
2033  PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
2034  LWLockRelease(partitionLock);
2035  elog(WARNING, "you don't own a lock of type %s",
2036  lockMethodTable->lockModeNames[lockmode]);
2037  RemoveLocalLock(locallock);
2038  return false;
2039  }
2040 
2041  /*
2042  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2043  */
2044  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2045 
2046  CleanUpLock(lock, proclock,
2047  lockMethodTable, locallock->hashcode,
2048  wakeupNeeded);
2049 
2050  LWLockRelease(partitionLock);
2051 
2052  RemoveLocalLock(locallock);
2053  return true;
2054 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
uint32 hashcode
Definition: lock.h:409
Definition: lwlock.h:32
static HTAB * LockMethodLocalHash
Definition: lock.c:255
int numLockOwners
Definition: lock.h:413
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2577
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
ResourceOwner CurrentResourceOwner
Definition: resowner.c:141
static int FastPathLocalUseCount
Definition: lock.c:171
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
#define MemSet(start, val, len)
Definition: c.h:941
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:662
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define LOG
Definition: elog.h:26
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:199
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1272
uint32 locktag_field2
Definition: lock.h:181
Definition: lock.h:284
uint16 LOCKMETHODID
Definition: lock.h:125
#define WARNING
Definition: elog.h:40
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:952
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:732
LWLock backendLock
Definition: proc.h:190
static HTAB * LockMethodLockHash
Definition: lock.c:253
LOCALLOCKOWNER * lockOwners
Definition: lock.h:415
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
LOCK * lock
Definition: lock.h:407
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
#define elog(elevel,...)
Definition: elog.h:226
int i
LOCK * myLock
Definition: lock.h:340
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1466
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1523
uint32 locktag_field1
Definition: lock.h:180
bool lockCleared
Definition: lock.h:412
const char *const * lockModeNames
Definition: lock.h:115
int numLockModes
Definition: lock.h:113

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2065 of file lock.c.

References Assert, PGPROC::backendLock, CleanUpLock(), DEFAULT_LOCKMETHOD, EligibleForRelationFastPath, elog, ERROR, FastPathUnGrantRelationLock(), LOCK::grantMask, hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, i, lengthof, LOCALLOCK_LOCKMETHOD, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_LOCKMETHOD, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLockByIndex, TwoPhaseLockRecord::lockmode, LOCALLOCK::lockOwners, LockRefindAndRelease(), LOCKTAG::locktag_field2, LockTagHashCode(), LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCALLOCKOWNER::nLocks, LOCALLOCK::nLocks, LOCK::nRequested, NUM_LOCK_PARTITIONS, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, offsetof, LOCALLOCKOWNER::owner, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), ResourceOwnerForgetLock(), SHMQueueNext(), status(), LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, LockMethodData::trace_flag, UnGrantLock(), and VirtualXactLockTableCleanup().

Referenced by DiscardAll(), ProcReleaseLocks(), and ShutdownPostgres().

2066 {
2068  LockMethod lockMethodTable;
2069  int i,
2070  numLockModes;
2071  LOCALLOCK *locallock;
2072  LOCK *lock;
2073  PROCLOCK *proclock;
2074  int partition;
2075  bool have_fast_path_lwlock = false;
2076 
2077  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2078  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2079  lockMethodTable = LockMethods[lockmethodid];
2080 
2081 #ifdef LOCK_DEBUG
2082  if (*(lockMethodTable->trace_flag))
2083  elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2084 #endif
2085 
2086  /*
2087  * Get rid of our fast-path VXID lock, if appropriate. Note that this is
2088  * the only way that the lock we hold on our own VXID can ever get
2089  * released: it is always and only released when a toplevel transaction
2090  * ends.
2091  */
2092  if (lockmethodid == DEFAULT_LOCKMETHOD)
2094 
2095  numLockModes = lockMethodTable->numLockModes;
2096 
2097  /*
2098  * First we run through the locallock table and get rid of unwanted
2099  * entries, then we scan the process's proclocks and get rid of those. We
2100  * do this separately because we may have multiple locallock entries
2101  * pointing to the same proclock, and we daren't end up with any dangling
2102  * pointers. Fast-path locks are cleaned up during the locallock table
2103  * scan, though.
2104  */
2106 
2107  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2108  {
2109  /*
2110  * If the LOCALLOCK entry is unused, we must've run out of shared
2111  * memory while trying to set up this lock. Just forget the local
2112  * entry.
2113  */
2114  if (locallock->nLocks == 0)
2115  {
2116  RemoveLocalLock(locallock);
2117  continue;
2118  }
2119 
2120  /* Ignore items that are not of the lockmethod to be removed */
2121  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2122  continue;
2123 
2124  /*
2125  * If we are asked to release all locks, we can just zap the entry.
2126  * Otherwise, must scan to see if there are session locks. We assume
2127  * there is at most one lockOwners entry for session locks.
2128  */
2129  if (!allLocks)
2130  {
2131  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2132 
2133  /* If session lock is above array position 0, move it down to 0 */
2134  for (i = 0; i < locallock->numLockOwners; i++)
2135  {
2136  if (lockOwners[i].owner == NULL)
2137  lockOwners[0] = lockOwners[i];
2138  else
2139  ResourceOwnerForgetLock(lockOwners[i].owner, locallock);
2140  }
2141 
2142  if (locallock->numLockOwners > 0 &&
2143  lockOwners[0].owner == NULL &&
2144  lockOwners[0].nLocks > 0)
2145  {
2146  /* Fix the locallock to show just the session locks */
2147  locallock->nLocks = lockOwners[0].nLocks;
2148  locallock->numLockOwners = 1;
2149  /* We aren't deleting this locallock, so done */
2150  continue;
2151  }
2152  else
2153  locallock->numLockOwners = 0;
2154  }
2155 
2156  /*
2157  * If the lock or proclock pointers are NULL, this lock was taken via
2158  * the relation fast-path (and is not known to have been transferred).
2159  */
2160  if (locallock->proclock == NULL || locallock->lock == NULL)
2161  {
2162  LOCKMODE lockmode = locallock->tag.mode;
2163  Oid relid;
2164 
2165  /* Verify that a fast-path lock is what we've got. */
2166  if (!EligibleForRelationFastPath(&locallock->tag.lock, lockmode))
2167  elog(PANIC, "locallock table corrupted");
2168 
2169  /*
2170  * If we don't currently hold the LWLock that protects our
2171  * fast-path data structures, we must acquire it before attempting
2172  * to release the lock via the fast-path. We will continue to
2173  * hold the LWLock until we're done scanning the locallock table,
2174  * unless we hit a transferred fast-path lock. (XXX is this
2175  * really such a good idea? There could be a lot of entries ...)
2176  */
2177  if (!have_fast_path_lwlock)
2178  {
2180  have_fast_path_lwlock = true;
2181  }
2182 
2183  /* Attempt fast-path release. */
2184  relid = locallock->tag.lock.locktag_field2;
2185  if (FastPathUnGrantRelationLock(relid, lockmode))
2186  {
2187  RemoveLocalLock(locallock);
2188  continue;
2189  }
2190 
2191  /*
2192  * Our lock, originally taken via the fast path, has been
2193  * transferred to the main lock table. That's going to require
2194  * some extra work, so release our fast-path lock before starting.
2195  */
2197  have_fast_path_lwlock = false;
2198 
2199  /*
2200  * Now dump the lock. We haven't got a pointer to the LOCK or
2201  * PROCLOCK in this case, so we have to handle this a bit
2202  * differently than a normal lock release. Unfortunately, this
2203  * requires an extra LWLock acquire-and-release cycle on the
2204  * partitionLock, but hopefully it shouldn't happen often.
2205  */
2206  LockRefindAndRelease(lockMethodTable, MyProc,
2207  &locallock->tag.lock, lockmode, false);
2208  RemoveLocalLock(locallock);
2209  continue;
2210  }
2211 
2212  /* Mark the proclock to show we need to release this lockmode */
2213  if (locallock->nLocks > 0)
2214  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
2215 
2216  /* And remove the locallock hashtable entry */
2217  RemoveLocalLock(locallock);
2218  }
2219 
2220  /* Done with the fast-path data structures */
2221  if (have_fast_path_lwlock)
2223 
2224  /*
2225  * Now, scan each lock partition separately.
2226  */
2227  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
2228  {
2229  LWLock *partitionLock;
2230  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
2231  PROCLOCK *nextplock;
2232 
2233  partitionLock = LockHashPartitionLockByIndex(partition);
2234 
2235  /*
2236  * If the proclock list for this partition is empty, we can skip
2237  * acquiring the partition lock. This optimization is trickier than
2238  * it looks, because another backend could be in process of adding
2239  * something to our proclock list due to promoting one of our
2240  * fast-path locks. However, any such lock must be one that we
2241  * decided not to delete above, so it's okay to skip it again now;
2242  * we'd just decide not to delete it again. We must, however, be
2243  * careful to re-fetch the list header once we've acquired the
2244  * partition lock, to be sure we have a valid, up-to-date pointer.
2245  * (There is probably no significant risk if pointer fetch/store is
2246  * atomic, but we don't wish to assume that.)
2247  *
2248  * XXX This argument assumes that the locallock table correctly
2249  * represents all of our fast-path locks. While allLocks mode
2250  * guarantees to clean up all of our normal locks regardless of the
2251  * locallock situation, we lose that guarantee for fast-path locks.
2252  * This is not ideal.
2253  */
2254  if (SHMQueueNext(procLocks, procLocks,
2255  offsetof(PROCLOCK, procLink)) == NULL)
2256  continue; /* needn't examine this partition */
2257 
2258  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2259 
2260  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2261  offsetof(PROCLOCK, procLink));
2262  proclock;
2263  proclock = nextplock)
2264  {
2265  bool wakeupNeeded = false;
2266 
2267  /* Get link first, since we may unlink/delete this proclock */
2268  nextplock = (PROCLOCK *)
2269  SHMQueueNext(procLocks, &proclock->procLink,
2270  offsetof(PROCLOCK, procLink));
2271 
2272  Assert(proclock->tag.myProc == MyProc);
2273 
2274  lock = proclock->tag.myLock;
2275 
2276  /* Ignore items that are not of the lockmethod to be removed */
2277  if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
2278  continue;
2279 
2280  /*
2281  * In allLocks mode, force release of all locks even if locallock
2282  * table had problems
2283  */
2284  if (allLocks)
2285  proclock->releaseMask = proclock->holdMask;
2286  else
2287  Assert((proclock->releaseMask & ~proclock->holdMask) == 0);
2288 
2289  /*
2290  * Ignore items that have nothing to be released, unless they have
2291  * holdMask == 0 and are therefore recyclable
2292  */
2293  if (proclock->releaseMask == 0 && proclock->holdMask != 0)
2294  continue;
2295 
2296  PROCLOCK_PRINT("LockReleaseAll", proclock);
2297  LOCK_PRINT("LockReleaseAll", lock, 0);
2298  Assert(lock->nRequested >= 0);
2299  Assert(lock->nGranted >= 0);
2300  Assert(lock->nGranted <= lock->nRequested);
2301  Assert((proclock->holdMask & ~lock->grantMask) == 0);
2302 
2303  /*
2304  * Release the previously-marked lock modes
2305  */
2306  for (i = 1; i <= numLockModes; i++)
2307  {
2308  if (proclock->releaseMask & LOCKBIT_ON(i))
2309  wakeupNeeded |= UnGrantLock(lock, i, proclock,
2310  lockMethodTable);
2311  }
2312  Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
2313  Assert(lock->nGranted <= lock->nRequested);
2314  LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2315 
2316  proclock->releaseMask = 0;
2317 
2318  /* CleanUpLock will wake up waiters if needed. */
2319  CleanUpLock(lock, proclock,
2320  lockMethodTable,
2321  LockTagHashCode(&lock->tag),
2322  wakeupNeeded);
2323  } /* loop over PROCLOCKs within this partition */
2324 
2325  LWLockRelease(partitionLock);
2326  } /* loop over partitions */
2327 
2328 #ifdef LOCK_DEBUG
2329  if (*(lockMethodTable->trace_flag))
2330  elog(LOG, "LockReleaseAll done");
2331 #endif
2332 }
PROCLOCKTAG tag
Definition: lock.h:347
Definition: lwlock.h:32
LOCALLOCKTAG tag
Definition: lock.h:404
static HTAB * LockMethodLocalHash
Definition: lock.c:255
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3013
void VirtualXactLockTableCleanup(void)
Definition: lock.c:4295
int numLockOwners
Definition: lock.h:413
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2577
LOCKTAG lock
Definition: lock.h:385
int LOCKMODE
Definition: lockdefs.h:26
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
int nRequested
Definition: lock.h:295
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
int64 nLocks
Definition: lock.h:398
LOCKTAG tag
Definition: lock.h:287
#define lengthof(array)
Definition: c.h:662
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:199
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:297
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1272
uint32 locktag_field2
Definition: lock.h:181
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:418
SHM_QUEUE procLink
Definition: lock.h:354
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:952
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:732
LWLock backendLock
Definition: proc.h:190
LOCALLOCKOWNER * lockOwners
Definition: lock.h:415
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
LOCK * lock
Definition: lock.h:407
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
#define elog(elevel,...)
Definition: elog.h:226
int i
const bool * trace_flag
Definition: lock.h:116
LOCK * myLock
Definition: lock.h:340
struct ResourceOwnerData * owner
Definition: lock.h:397
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1466
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1523
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define offsetof(type, field)
Definition: c.h:655
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:300
int numLockModes
Definition: lock.h:113
LOCKMASK releaseMask
Definition: lock.h:352

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2369 of file lock.c.

References hash_seq_init(), hash_seq_search(), i, ReleaseLockIfHeld(), and status().

Referenced by ResourceOwnerReleaseInternal().

2370 {
2371  if (locallocks == NULL)
2372  {
2374  LOCALLOCK *locallock;
2375 
2377 
2378  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2379  ReleaseLockIfHeld(locallock, false);
2380  }
2381  else
2382  {
2383  int i;
2384 
2385  for (i = nlocks - 1; i >= 0; i--)
2386  ReleaseLockIfHeld(locallocks[i], false);
2387  }
2388 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2404
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

Definition at line 2339 of file lock.c.

References elog, ERROR, hash_seq_init(), hash_seq_search(), lengthof, LOCALLOCK_LOCKMETHOD, ReleaseLockIfHeld(), and status().

Referenced by pg_advisory_unlock_all().

2340 {
2342  LOCALLOCK *locallock;
2343 
2344  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2345  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2346 
2348 
2349  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2350  {
2351  /* Ignore items that are not of the specified lock method */
2352  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2353  continue;
2354 
2355  ReleaseLockIfHeld(locallock, true);
2356  }
2357 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
#define lengthof(array)
Definition: c.h:662
#define ERROR
Definition: elog.h:43
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2404
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:418
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#define elog(elevel,...)
Definition: elog.h:226
static const LockMethod LockMethods[]
Definition: lock.c:150
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ LockShmemSize()

Size LockShmemSize ( void  )

Definition at line 3412 of file lock.c.

References add_size(), hash_estimate_size(), and NLOCKENTS.

Referenced by CreateSharedMemoryAndSemaphores().

3413 {
3414  Size size = 0;
3415  long max_table_size;
3416 
3417  /* lock hash table */
3418  max_table_size = NLOCKENTS();
3419  size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3420 
3421  /* proclock hash table */
3422  max_table_size *= 2;
3423  size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3424 
3425  /*
3426  * Since NLOCKENTS is only an estimate, add 10% safety margin.
3427  */
3428  size = add_size(size, size / 10);
3429 
3430  return size;
3431 }
#define NLOCKENTS()
Definition: lock.c:56
Definition: lock.h:284
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:732
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:466
Definition: lock.h:344

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 490 of file lock.c.

References get_hash_value().

Referenced by CheckDeadLock(), GetLockConflicts(), lock_twophase_recover(), LockAcquireExtended(), LockRefindAndRelease(), LockReleaseAll(), LockWaiterCount(), proclock_hash(), and VirtualXactLock().

491 {
492  return get_hash_value(LockMethodLockHash, (const void *) locktag);
493 }
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:860
static HTAB * LockMethodLockHash
Definition: lock.c:253

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

Definition at line 4438 of file lock.c.

References Assert, elog, ERROR, HASH_FIND, hash_search_with_hash_value(), lengthof, LockHashPartitionLock, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_lockmethodid, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), and LOCK::nRequested.

Referenced by RelationExtensionLockWaiterCount().

4439 {
4440  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4441  LOCK *lock;
4442  bool found;
4443  uint32 hashcode;
4444  LWLock *partitionLock;
4445  int waiters = 0;
4446 
4447  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4448  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4449 
4450  hashcode = LockTagHashCode(locktag);
4451  partitionLock = LockHashPartitionLock(hashcode);
4452  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4453 
4455  (const void *) locktag,
4456  hashcode,
4457  HASH_FIND,
4458  &found);
4459  if (found)
4460  {
4461  Assert(lock != NULL);
4462  waiters = lock->nRequested;
4463  }
4464  LWLockRelease(partitionLock);
4465 
4466  return waiters;
4467 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
Definition: lwlock.h:32
int nRequested
Definition: lock.h:295
#define LockHashPartitionLock(hashcode)
Definition: lock.h:499
#define lengthof(array)
Definition: c.h:662
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:358
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:732
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
uint8 locktag_lockmethodid
Definition: lock.h:185
#define elog(elevel,...)
Definition: elog.h:226
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

Definition at line 1684 of file lock.c.

References Assert, LOCALLOCK::lockCleared, and LOCALLOCK::nLocks.

Referenced by ConditionalLockRelation(), ConditionalLockRelationOid(), LockRelation(), and LockRelationOid().

1685 {
1686  Assert(locallock->nLocks > 0);
1687  locallock->lockCleared = true;
1688 }
#define Assert(condition)
Definition: c.h:732
int64 nLocks
Definition: lock.h:410
bool lockCleared
Definition: lock.h:412

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

Definition at line 3220 of file lock.c.

References Assert, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), LOCK::grantMask, PROCLOCK::groupLeader, hash_seq_init(), hash_seq_search(), hash_update_hash_key(), PROCLOCK::holdMask, i, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartitionLockByIndex, LOCALLOCK::lockOwners, LOCKTAG::locktag_type, LOCKTAG_VIRTUALTRANSACTION, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCALLOCK::nLocks, LOCK::nRequested, NUM_LOCK_PARTITIONS, LOCALLOCK::numLockOwners, offsetof, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), SHMQueueDelete(), SHMQueueInsertBefore(), SHMQueueNext(), START_CRIT_SECTION, status(), LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, and TwoPhaseGetDummyProc().

Referenced by PrepareTransaction().

3221 {
3222  PGPROC *newproc = TwoPhaseGetDummyProc(xid);
3224  LOCALLOCK *locallock;
3225  LOCK *lock;
3226  PROCLOCK *proclock;
3227  PROCLOCKTAG proclocktag;
3228  int partition;
3229 
3230  /* Can't prepare a lock group follower. */
3231  Assert(MyProc->lockGroupLeader == NULL ||
3233 
3234  /* This is a critical section: any error means big trouble */
3236 
3237  /*
3238  * First we run through the locallock table and get rid of unwanted
3239  * entries, then we scan the process's proclocks and transfer them to the
3240  * target proc.
3241  *
3242  * We do this separately because we may have multiple locallock entries
3243  * pointing to the same proclock, and we daren't end up with any dangling
3244  * pointers.
3245  */
3247 
3248  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3249  {
3250  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3251  bool haveSessionLock;
3252  bool haveXactLock;
3253  int i;
3254 
3255  if (locallock->proclock == NULL || locallock->lock == NULL)
3256  {
3257  /*
3258  * We must've run out of shared memory while trying to set up this
3259  * lock. Just forget the local entry.
3260  */
3261  Assert(locallock->nLocks == 0);
3262  RemoveLocalLock(locallock);
3263  continue;
3264  }
3265 
3266  /* Ignore VXID locks */
3267  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3268  continue;
3269 
3270  /* Scan to see whether we hold it at session or transaction level */
3271  haveSessionLock = haveXactLock = false;
3272  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3273  {
3274  if (lockOwners[i].owner == NULL)
3275  haveSessionLock = true;
3276  else
3277  haveXactLock = true;
3278  }
3279 
3280  /* Ignore it if we have only session lock */
3281  if (!haveXactLock)
3282  continue;
3283 
3284  /* This can't happen, because we already checked it */
3285  if (haveSessionLock)
3286  ereport(PANIC,
3287  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3288  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3289 
3290  /* Mark the proclock to show we need to release this lockmode */
3291  if (locallock->nLocks > 0)
3292  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3293 
3294  /* And remove the locallock hashtable entry */
3295  RemoveLocalLock(locallock);
3296  }
3297 
3298  /*
3299  * Now, scan each lock partition separately.
3300  */
3301  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3302  {
3303  LWLock *partitionLock;
3304  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
3305  PROCLOCK *nextplock;
3306 
3307  partitionLock = LockHashPartitionLockByIndex(partition);
3308 
3309  /*
3310  * If the proclock list for this partition is empty, we can skip
3311  * acquiring the partition lock. This optimization is safer than the
3312  * situation in LockReleaseAll, because we got rid of any fast-path
3313  * locks during AtPrepare_Locks, so there cannot be any case where
3314  * another backend is adding something to our lists now. For safety,
3315  * though, we code this the same way as in LockReleaseAll.
3316  */
3317  if (SHMQueueNext(procLocks, procLocks,
3318  offsetof(PROCLOCK, procLink)) == NULL)
3319  continue; /* needn't examine this partition */
3320 
3321  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3322 
3323  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3324  offsetof(PROCLOCK, procLink));
3325  proclock;
3326  proclock = nextplock)
3327  {
3328  /* Get link first, since we may unlink/relink this proclock */
3329  nextplock = (PROCLOCK *)
3330  SHMQueueNext(procLocks, &proclock->procLink,
3331  offsetof(PROCLOCK, procLink));
3332 
3333  Assert(proclock->tag.myProc == MyProc);
3334 
3335  lock = proclock->tag.myLock;
3336 
3337  /* Ignore VXID locks */
3339  continue;
3340 
3341  PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3342  LOCK_PRINT("PostPrepare_Locks", lock, 0);
3343  Assert(lock->nRequested >= 0);
3344  Assert(lock->nGranted >= 0);
3345  Assert(lock->nGranted <= lock->nRequested);
3346  Assert((proclock->holdMask & ~lock->grantMask) == 0);
3347 
3348  /* Ignore it if nothing to release (must be a session lock) */
3349  if (proclock->releaseMask == 0)
3350  continue;
3351 
3352  /* Else we should be releasing all locks */
3353  if (proclock->releaseMask != proclock->holdMask)
3354  elog(PANIC, "we seem to have dropped a bit somewhere");
3355 
3356  /*
3357  * We cannot simply modify proclock->tag.myProc to reassign
3358  * ownership of the lock, because that's part of the hash key and
3359  * the proclock would then be in the wrong hash chain. Instead
3360  * use hash_update_hash_key. (We used to create a new hash entry,
3361  * but that risks out-of-memory failure if other processes are
3362  * busy making proclocks too.) We must unlink the proclock from
3363  * our procLink chain and put it into the new proc's chain, too.
3364  *
3365  * Note: the updated proclock hash key will still belong to the
3366  * same hash partition, cf proclock_hash(). So the partition lock
3367  * we already hold is sufficient for this.
3368  */
3369  SHMQueueDelete(&proclock->procLink);
3370 
3371  /*
3372  * Create the new hash key for the proclock.
3373  */
3374  proclocktag.myLock = lock;
3375  proclocktag.myProc = newproc;
3376 
3377  /*
3378  * Update groupLeader pointer to point to the new proc. (We'd
3379  * better not be a member of somebody else's lock group!)
3380  */
3381  Assert(proclock->groupLeader == proclock->tag.myProc);
3382  proclock->groupLeader = newproc;
3383 
3384  /*
3385  * Update the proclock. We should not find any existing entry for
3386  * the same hash key, since there can be only one entry for any
3387  * given lock with my own proc.
3388  */
3390  (void *) proclock,
3391  (void *) &proclocktag))
3392  elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3393 
3394  /* Re-link into the new proc's proclock list */
3395  SHMQueueInsertBefore(&(newproc->myProcLocks[partition]),
3396  &proclock->procLink);
3397 
3398  PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3399  } /* loop over PROCLOCKs within this partition */
3400 
3401  LWLockRelease(partitionLock);
3402  } /* loop over partitions */
3403 
3404  END_CRIT_SECTION();
3405 }
PROCLOCKTAG tag
Definition: lock.h:347
PGPROC * TwoPhaseGetDummyProc(TransactionId xid)
Definition: twophase.c:867
Definition: lwlock.h:32
LOCALLOCKTAG tag
Definition: lock.h:404
static HTAB * LockMethodLocalHash
Definition: lock.c:255
int numLockOwners
Definition: lock.h:413
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
int nRequested
Definition: lock.h:295
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
LOCKTAG tag
Definition: lock.h:287
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:297
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1725
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1272
Definition: lock.h:284
#define ereport(elevel, rest)
Definition: elog.h:141
SHM_QUEUE procLink
Definition: lock.h:354
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:732
LOCALLOCKOWNER * lockOwners
Definition: lock.h:415
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1121
bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr)
Definition: dynahash.c:1115
LOCK * lock
Definition: lock.h:407
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog(elevel,...)
Definition: elog.h:226
int i
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
LOCK * myLock
Definition: lock.h:340
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Definition: proc.h:95
PGPROC * lockGroupLeader
Definition: proc.h:203
#define offsetof(type, field)
Definition: c.h:655
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
PGPROC * groupLeader
Definition: lock.h:350
LOCKMASK releaseMask
Definition: lock.h:352

◆ RememberSimpleDeadLock()

void RememberSimpleDeadLock ( PGPROC proc1,
LOCKMODE  lockmode,
LOCK lock,
PGPROC proc2 
)

Definition at line 1149 of file deadlock.c.

References DEADLOCK_INFO::lockmode, DEADLOCK_INFO::locktag, nDeadlockDetails, DEADLOCK_INFO::pid, PGPROC::pid, LOCK::tag, PGPROC::waitLock, and PGPROC::waitLockMode.

Referenced by ProcSleep().

1153 {
1154  DEADLOCK_INFO *info = &deadlockDetails[0];
1155 
1156  info->locktag = lock->tag;
1157  info->lockmode = lockmode;
1158  info->pid = proc1->pid;
1159  info++;
1160  info->locktag = proc2->waitLock->tag;
1161  info->lockmode = proc2->waitLockMode;
1162  info->pid = proc2->pid;
1163  nDeadlockDetails = 2;
1164 }
LOCKMODE lockmode
Definition: deadlock.c:74
LOCKMODE waitLockMode
Definition: proc.h:141
LOCKTAG tag
Definition: lock.h:287
static int nDeadlockDetails
Definition: deadlock.c:125
LOCK * waitLock
Definition: proc.h:139
static DEADLOCK_INFO *