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 LockHeldByMe (const LOCKTAG *locktag, LOCKMODE lockmode)
 
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 CheckRelationLockedByMe(), 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 1666 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

1667 {
1668  uint32 fasthashcode;
1669  LOCALLOCK *locallock = StrongLockInProgress;
1670 
1671  if (locallock == NULL)
1672  return;
1673 
1674  fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1675  Assert(locallock->holdsStrongLockCount == true);
1677  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1678  FastPathStrongRelationLocks->count[fasthashcode]--;
1679  locallock->holdsStrongLockCount = false;
1680  StrongLockInProgress = NULL;
1682 }
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 3134 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().

3135 {
3137  LOCALLOCK *locallock;
3138 
3139  /*
3140  * For the most part, we don't need to touch shared memory for this ---
3141  * all the necessary state information is in the locallock table.
3142  * Fast-path locks are an exception, however: we move any such locks to
3143  * the main table before allowing PREPARE TRANSACTION to succeed.
3144  */
3146 
3147  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3148  {
3149  TwoPhaseLockRecord record;
3150  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3151  bool haveSessionLock;
3152  bool haveXactLock;
3153  int i;
3154 
3155  /*
3156  * Ignore VXID locks. We don't want those to be held by prepared
3157  * transactions, since they aren't meaningful after a restart.
3158  */
3159  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3160  continue;
3161 
3162  /* Ignore it if we don't actually hold the lock */
3163  if (locallock->nLocks <= 0)
3164  continue;
3165 
3166  /* Scan to see whether we hold it at session or transaction level */
3167  haveSessionLock = haveXactLock = false;
3168  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3169  {
3170  if (lockOwners[i].owner == NULL)
3171  haveSessionLock = true;
3172  else
3173  haveXactLock = true;
3174  }
3175 
3176  /* Ignore it if we have only session lock */
3177  if (!haveXactLock)
3178  continue;
3179 
3180  /*
3181  * If we have both session- and transaction-level locks, fail. This
3182  * should never happen with regular locks, since we only take those at
3183  * session level in some special operations like VACUUM. It's
3184  * possible to hit this with advisory locks, though.
3185  *
3186  * It would be nice if we could keep the session hold and give away
3187  * the transactional hold to the prepared xact. However, that would
3188  * require two PROCLOCK objects, and we cannot be sure that another
3189  * PROCLOCK will be available when it comes time for PostPrepare_Locks
3190  * to do the deed. So for now, we error out while we can still do so
3191  * safely.
3192  */
3193  if (haveSessionLock)
3194  ereport(ERROR,
3195  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3196  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3197 
3198  /*
3199  * If the local lock was taken via the fast-path, we need to move it
3200  * to the primary lock table, or just get a pointer to the existing
3201  * primary lock table entry if by chance it's already been
3202  * transferred.
3203  */
3204  if (locallock->proclock == NULL)
3205  {
3206  locallock->proclock = FastPathGetRelationLockEntry(locallock);
3207  locallock->lock = locallock->proclock->tag.myLock;
3208  }
3209 
3210  /*
3211  * Arrange to not release any strong lock count held by this lock
3212  * entry. We must retain the count until the prepared transaction is
3213  * committed or rolled back.
3214  */
3215  locallock->holdsStrongLockCount = false;
3216 
3217  /*
3218  * Create a 2PC record.
3219  */
3220  memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3221  record.lockmode = locallock->tag.mode;
3222 
3224  &record, sizeof(TwoPhaseLockRecord));
3225  }
3226 }
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:2719
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
Definition: lock.h:178
int errcode(int sqlerrcode)
Definition: elog.c:570
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:784
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:1022
Definition: lock.h:284
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1613
#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:974
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:3920
LOCKMODE lockmode
Definition: deadlock.c:74
int errcode(int sqlerrcode)
Definition: elog.c:570
int errdetail_internal(const char *fmt,...)
Definition: elog.c:887
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:1047
static int nDeadlockDetails
Definition: deadlock.c:125
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:163
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:62
int errdetail_log(const char *fmt,...)
Definition: elog.c:908
#define ereport(elevel, rest)
Definition: elog.h:141
const char * pgstat_get_backend_current_activity(int pid, bool checkUser)
Definition: pgstat.c:3960
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:175
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:784
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 3657 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().

3658 {
3659  BlockedProcsData *data;
3660  PGPROC *proc;
3661  int i;
3662 
3663  data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
3664 
3665  /*
3666  * Guess how much space we'll need, and preallocate. Most of the time
3667  * this will avoid needing to do repalloc while holding the LWLocks. (We
3668  * assume, but check with an Assert, that MaxBackends is enough entries
3669  * for the procs[] array; the other two could need enlargement, though.)
3670  */
3671  data->nprocs = data->nlocks = data->npids = 0;
3672  data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3673  data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
3674  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3675  data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3676 
3677  /*
3678  * In order to search the ProcArray for blocked_pid and assume that that
3679  * entry won't immediately disappear under us, we must hold ProcArrayLock.
3680  * In addition, to examine the lock grouping fields of any other backend,
3681  * we must hold all the hash partition locks. (Only one of those locks is
3682  * actually relevant for any one lock group, but we can't know which one
3683  * ahead of time.) It's fairly annoying to hold all those locks
3684  * throughout this, but it's no worse than GetLockStatusData(), and it
3685  * does have the advantage that we're guaranteed to return a
3686  * self-consistent instantaneous state.
3687  */
3688  LWLockAcquire(ProcArrayLock, LW_SHARED);
3689 
3690  proc = BackendPidGetProcWithLock(blocked_pid);
3691 
3692  /* Nothing to do if it's gone */
3693  if (proc != NULL)
3694  {
3695  /*
3696  * Acquire lock on the entire shared lock data structure. See notes
3697  * in GetLockStatusData().
3698  */
3699  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3701 
3702  if (proc->lockGroupLeader == NULL)
3703  {
3704  /* Easy case, proc is not a lock group member */
3705  GetSingleProcBlockerStatusData(proc, data);
3706  }
3707  else
3708  {
3709  /* Examine all procs in proc's lock group */
3710  dlist_iter iter;
3711 
3713  {
3714  PGPROC *memberProc;
3715 
3716  memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
3717  GetSingleProcBlockerStatusData(memberProc, data);
3718  }
3719  }
3720 
3721  /*
3722  * And release locks. See notes in GetLockStatusData().
3723  */
3724  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3726 
3727  Assert(data->nprocs <= data->maxprocs);
3728  }
3729 
3730  LWLockRelease(ProcArrayLock);
3731 
3732  return data;
3733 }
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:2402
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition: lock.c:3737
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:502
int MaxBackends
Definition: globals.c:135
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 2820 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().

2821 {
2822  static VirtualTransactionId *vxids;
2823  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
2824  LockMethod lockMethodTable;
2825  LOCK *lock;
2826  LOCKMASK conflictMask;
2827  SHM_QUEUE *procLocks;
2828  PROCLOCK *proclock;
2829  uint32 hashcode;
2830  LWLock *partitionLock;
2831  int count = 0;
2832  int fast_count = 0;
2833 
2834  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2835  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2836  lockMethodTable = LockMethods[lockmethodid];
2837  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2838  elog(ERROR, "unrecognized lock mode: %d", lockmode);
2839 
2840  /*
2841  * Allocate memory to store results, and fill with InvalidVXID. We only
2842  * need enough space for MaxBackends + a terminator, since prepared xacts
2843  * don't count. InHotStandby allocate once in TopMemoryContext.
2844  */
2845  if (InHotStandby)
2846  {
2847  if (vxids == NULL)
2848  vxids = (VirtualTransactionId *)
2850  sizeof(VirtualTransactionId) * (MaxBackends + 1));
2851  }
2852  else
2853  vxids = (VirtualTransactionId *)
2854  palloc0(sizeof(VirtualTransactionId) * (MaxBackends + 1));
2855 
2856  /* Compute hash code and partition lock, and look up conflicting modes. */
2857  hashcode = LockTagHashCode(locktag);
2858  partitionLock = LockHashPartitionLock(hashcode);
2859  conflictMask = lockMethodTable->conflictTab[lockmode];
2860 
2861  /*
2862  * Fast path locks might not have been entered in the primary lock table.
2863  * If the lock we're dealing with could conflict with such a lock, we must
2864  * examine each backend's fast-path array for conflicts.
2865  */
2866  if (ConflictsWithRelationFastPath(locktag, lockmode))
2867  {
2868  int i;
2869  Oid relid = locktag->locktag_field2;
2870  VirtualTransactionId vxid;
2871 
2872  /*
2873  * Iterate over relevant PGPROCs. Anything held by a prepared
2874  * transaction will have been transferred to the primary lock table,
2875  * so we need not worry about those. This is all a bit fuzzy, because
2876  * new locks could be taken after we've visited a particular
2877  * partition, but the callers had better be prepared to deal with that
2878  * anyway, since the locks could equally well be taken between the
2879  * time we return the value and the time the caller does something
2880  * with it.
2881  */
2882  for (i = 0; i < ProcGlobal->allProcCount; i++)
2883  {
2884  PGPROC *proc = &ProcGlobal->allProcs[i];
2885  uint32 f;
2886 
2887  /* A backend never blocks itself */
2888  if (proc == MyProc)
2889  continue;
2890 
2892 
2893  /*
2894  * If the target backend isn't referencing the same database as
2895  * the lock, then we needn't examine the individual relation IDs
2896  * at all; none of them can be relevant.
2897  *
2898  * See FastPathTransferLocks() for discussion of why we do this
2899  * test after acquiring the lock.
2900  */
2901  if (proc->databaseId != locktag->locktag_field1)
2902  {
2903  LWLockRelease(&proc->backendLock);
2904  continue;
2905  }
2906 
2907  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2908  {
2909  uint32 lockmask;
2910 
2911  /* Look for an allocated slot matching the given relid. */
2912  if (relid != proc->fpRelId[f])
2913  continue;
2914  lockmask = FAST_PATH_GET_BITS(proc, f);
2915  if (!lockmask)
2916  continue;
2917  lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
2918 
2919  /*
2920  * There can only be one entry per relation, so if we found it
2921  * and it doesn't conflict, we can skip the rest of the slots.
2922  */
2923  if ((lockmask & conflictMask) == 0)
2924  break;
2925 
2926  /* Conflict! */
2927  GET_VXID_FROM_PGPROC(vxid, *proc);
2928 
2929  /*
2930  * If we see an invalid VXID, then either the xact has already
2931  * committed (or aborted), or it's a prepared xact. In either
2932  * case we may ignore it.
2933  */
2934  if (VirtualTransactionIdIsValid(vxid))
2935  vxids[count++] = vxid;
2936 
2937  /* No need to examine remaining slots. */
2938  break;
2939  }
2940 
2941  LWLockRelease(&proc->backendLock);
2942  }
2943  }
2944 
2945  /* Remember how many fast-path conflicts we found. */
2946  fast_count = count;
2947 
2948  /*
2949  * Look up the lock object matching the tag.
2950  */
2951  LWLockAcquire(partitionLock, LW_SHARED);
2952 
2954  (const void *) locktag,
2955  hashcode,
2956  HASH_FIND,
2957  NULL);
2958  if (!lock)
2959  {
2960  /*
2961  * If the lock object doesn't exist, there is nothing holding a lock
2962  * on this lockable object.
2963  */
2964  LWLockRelease(partitionLock);
2965  vxids[count].backendId = InvalidBackendId;
2967  return vxids;
2968  }
2969 
2970  /*
2971  * Examine each existing holder (or awaiter) of the lock.
2972  */
2973 
2974  procLocks = &(lock->procLocks);
2975 
2976  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2977  offsetof(PROCLOCK, lockLink));
2978 
2979  while (proclock)
2980  {
2981  if (conflictMask & proclock->holdMask)
2982  {
2983  PGPROC *proc = proclock->tag.myProc;
2984 
2985  /* A backend never blocks itself */
2986  if (proc != MyProc)
2987  {
2988  VirtualTransactionId vxid;
2989 
2990  GET_VXID_FROM_PGPROC(vxid, *proc);
2991 
2992  /*
2993  * If we see an invalid VXID, then either the xact has already
2994  * committed (or aborted), or it's a prepared xact. In either
2995  * case we may ignore it.
2996  */
2997  if (VirtualTransactionIdIsValid(vxid))
2998  {
2999  int i;
3000 
3001  /* Avoid duplicate entries. */
3002  for (i = 0; i < fast_count; ++i)
3003  if (VirtualTransactionIdEquals(vxids[i], vxid))
3004  break;
3005  if (i >= fast_count)
3006  vxids[count++] = vxid;
3007  }
3008  }
3009  }
3010 
3011  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3012  offsetof(PROCLOCK, lockLink));
3013  }
3014 
3015  LWLockRelease(partitionLock);
3016 
3017  if (count > MaxBackends) /* should never happen */
3018  elog(PANIC, "too many conflicting locks found");
3019 
3020  vxids[count].backendId = InvalidBackendId;
3022  return vxids;
3023 }
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:135
#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 3920 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 CheckRelationLockedByMe(), DeadLockReport(), pg_lock_status(), and ProcSleep().

3921 {
3922  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
3923  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
3924  return LockMethods[lockmethodid]->lockModeNames[mode];
3925 }
#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 3473 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().

3474 {
3475  LockData *data;
3476  PROCLOCK *proclock;
3477  HASH_SEQ_STATUS seqstat;
3478  int els;
3479  int el;
3480  int i;
3481 
3482  data = (LockData *) palloc(sizeof(LockData));
3483 
3484  /* Guess how much space we'll need. */
3485  els = MaxBackends;
3486  el = 0;
3487  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3488 
3489  /*
3490  * First, we iterate through the per-backend fast-path arrays, locking
3491  * them one at a time. This might produce an inconsistent picture of the
3492  * system state, but taking all of those LWLocks at the same time seems
3493  * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3494  * matter too much, because none of these locks can be involved in lock
3495  * conflicts anyway - anything that might must be present in the main lock
3496  * table. (For the same reason, we don't sweat about making leaderPid
3497  * completely valid. We cannot safely dereference another backend's
3498  * lockGroupLeader field without holding all lock partition locks, and
3499  * it's not worth that.)
3500  */
3501  for (i = 0; i < ProcGlobal->allProcCount; ++i)
3502  {
3503  PGPROC *proc = &ProcGlobal->allProcs[i];
3504  uint32 f;
3505 
3507 
3508  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
3509  {
3510  LockInstanceData *instance;
3511  uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3512 
3513  /* Skip unallocated slots. */
3514  if (!lockbits)
3515  continue;
3516 
3517  if (el >= els)
3518  {
3519  els += MaxBackends;
3520  data->locks = (LockInstanceData *)
3521  repalloc(data->locks, sizeof(LockInstanceData) * els);
3522  }
3523 
3524  instance = &data->locks[el];
3525  SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3526  proc->fpRelId[f]);
3527  instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3528  instance->waitLockMode = NoLock;
3529  instance->backend = proc->backendId;
3530  instance->lxid = proc->lxid;
3531  instance->pid = proc->pid;
3532  instance->leaderPid = proc->pid;
3533  instance->fastpath = true;
3534 
3535  el++;
3536  }
3537 
3538  if (proc->fpVXIDLock)
3539  {
3540  VirtualTransactionId vxid;
3541  LockInstanceData *instance;
3542 
3543  if (el >= els)
3544  {
3545  els += MaxBackends;
3546  data->locks = (LockInstanceData *)
3547  repalloc(data->locks, sizeof(LockInstanceData) * els);
3548  }
3549 
3550  vxid.backendId = proc->backendId;
3552 
3553  instance = &data->locks[el];
3554  SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3555  instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3556  instance->waitLockMode = NoLock;
3557  instance->backend = proc->backendId;
3558  instance->lxid = proc->lxid;
3559  instance->pid = proc->pid;
3560  instance->leaderPid = proc->pid;
3561  instance->fastpath = true;
3562 
3563  el++;
3564  }
3565 
3566  LWLockRelease(&proc->backendLock);
3567  }
3568 
3569  /*
3570  * Next, acquire lock on the entire shared lock data structure. We do
3571  * this so that, at least for locks in the primary lock table, the state
3572  * will be self-consistent.
3573  *
3574  * Since this is a read-only operation, we take shared instead of
3575  * exclusive lock. There's not a whole lot of point to this, because all
3576  * the normal operations require exclusive lock, but it doesn't hurt
3577  * anything either. It will at least allow two backends to do
3578  * GetLockStatusData in parallel.
3579  *
3580  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3581  */
3582  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3584 
3585  /* Now we can safely count the number of proclocks */
3587  if (data->nelements > els)
3588  {
3589  els = data->nelements;
3590  data->locks = (LockInstanceData *)
3591  repalloc(data->locks, sizeof(LockInstanceData) * els);
3592  }
3593 
3594  /* Now scan the tables to copy the data */
3596 
3597  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3598  {
3599  PGPROC *proc = proclock->tag.myProc;
3600  LOCK *lock = proclock->tag.myLock;
3601  LockInstanceData *instance = &data->locks[el];
3602 
3603  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3604  instance->holdMask = proclock->holdMask;
3605  if (proc->waitLock == proclock->tag.myLock)
3606  instance->waitLockMode = proc->waitLockMode;
3607  else
3608  instance->waitLockMode = NoLock;
3609  instance->backend = proc->backendId;
3610  instance->lxid = proc->lxid;
3611  instance->pid = proc->pid;
3612  instance->leaderPid = proclock->groupLeader->pid;
3613  instance->fastpath = false;
3614 
3615  el++;
3616  }
3617 
3618  /*
3619  * And release locks. We do this in reverse order for two reasons: (1)
3620  * Anyone else who needs more than one of the locks will be trying to lock
3621  * them in increasing order; we don't want to release the other process
3622  * until it can get all the locks it needs. (2) This avoids O(N^2)
3623  * behavior inside LWLockRelease.
3624  */
3625  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3627 
3628  Assert(el == data->nelements);
3629 
3630  return data;
3631 }
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:135
#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 3837 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().

3838 {
3839  xl_standby_lock *accessExclusiveLocks;
3840  PROCLOCK *proclock;
3841  HASH_SEQ_STATUS seqstat;
3842  int i;
3843  int index;
3844  int els;
3845 
3846  /*
3847  * Acquire lock on the entire shared lock data structure.
3848  *
3849  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3850  */
3851  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3853 
3854  /* Now we can safely count the number of proclocks */
3856 
3857  /*
3858  * Allocating enough space for all locks in the lock table is overkill,
3859  * but it's more convenient and faster than having to enlarge the array.
3860  */
3861  accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
3862 
3863  /* Now scan the tables to copy the data */
3865 
3866  /*
3867  * If lock is a currently granted AccessExclusiveLock then it will have
3868  * just one proclock holder, so locks are never accessed twice in this
3869  * particular case. Don't copy this code for use elsewhere because in the
3870  * general case this will give you duplicate locks when looking at
3871  * non-exclusive lock types.
3872  */
3873  index = 0;
3874  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3875  {
3876  /* make sure this definition matches the one used in LockAcquire */
3877  if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
3878  proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION)
3879  {
3880  PGPROC *proc = proclock->tag.myProc;
3881  PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno];
3882  LOCK *lock = proclock->tag.myLock;
3883  TransactionId xid = pgxact->xid;
3884 
3885  /*
3886  * Don't record locks for transactions if we know they have
3887  * already issued their WAL record for commit but not yet released
3888  * lock. It is still possible that we see locks held by already
3889  * complete transactions, if they haven't yet zeroed their xids.
3890  */
3891  if (!TransactionIdIsValid(xid))
3892  continue;
3893 
3894  accessExclusiveLocks[index].xid = xid;
3895  accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
3896  accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
3897 
3898  index++;
3899  }
3900  }
3901 
3902  Assert(index <= els);
3903 
3904  /*
3905  * And release locks. We do this in reverse order for two reasons: (1)
3906  * Anyone else who needs more than one of the locks will be trying to lock
3907  * them in increasing order; we don't want to release the other process
3908  * until it can get all the locks it needs. (2) This avoids O(N^2)
3909  * behavior inside LWLockRelease.
3910  */
3911  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3913 
3914  *nlocks = index;
3915  return accessExclusiveLocks;
3916 }
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:54
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 1695 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

1696 {
1698 }
static LOCALLOCK * awaitedLock
Definition: lock.c:260
static ResourceOwner awaitedOwner
Definition: lock.c:261
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1601

◆ GrantLock()

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

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

1468 {
1469  lock->nGranted++;
1470  lock->granted[lockmode]++;
1471  lock->grantMask |= LOCKBIT_ON(lockmode);
1472  if (lock->granted[lockmode] == lock->requested[lockmode])
1473  lock->waitMask &= LOCKBIT_OFF(lockmode);
1474  proclock->holdMask |= LOCKBIT_ON(lockmode);
1475  LOCK_PRINT("GrantLock", lock, lockmode);
1476  Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1477  Assert(lock->nGranted <= lock->nRequested);
1478 }
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:135
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 4272 of file lock.c.

References lock_twophase_postcommit().

4274 {
4275  lock_twophase_postcommit(xid, info, recdata, len);
4276 }
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
Definition: lock.c:4246

◆ lock_twophase_postcommit()

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

Definition at line 4246 of file lock.c.

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

Referenced by lock_twophase_postabort().

4248 {
4249  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4250  PGPROC *proc = TwoPhaseGetDummyProc(xid);
4251  LOCKTAG *locktag;
4252  LOCKMETHODID lockmethodid;
4253  LockMethod lockMethodTable;
4254 
4255  Assert(len == sizeof(TwoPhaseLockRecord));
4256  locktag = &rec->locktag;
4257  lockmethodid = locktag->locktag_lockmethodid;
4258 
4259  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4260  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4261  lockMethodTable = LockMethods[lockmethodid];
4262 
4263  LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4264 }
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:3037
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 4033 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.

4035 {
4036  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4037  PGPROC *proc = TwoPhaseGetDummyProc(xid);
4038  LOCKTAG *locktag;
4039  LOCKMODE lockmode;
4040  LOCKMETHODID lockmethodid;
4041  LOCK *lock;
4042  PROCLOCK *proclock;
4043  PROCLOCKTAG proclocktag;
4044  bool found;
4045  uint32 hashcode;
4046  uint32 proclock_hashcode;
4047  int partition;
4048  LWLock *partitionLock;
4049  LockMethod lockMethodTable;
4050 
4051  Assert(len == sizeof(TwoPhaseLockRecord));
4052  locktag = &rec->locktag;
4053  lockmode = rec->lockmode;
4054  lockmethodid = locktag->locktag_lockmethodid;
4055 
4056  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4057  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4058  lockMethodTable = LockMethods[lockmethodid];
4059 
4060  hashcode = LockTagHashCode(locktag);
4061  partition = LockHashPartition(hashcode);
4062  partitionLock = LockHashPartitionLock(hashcode);
4063 
4064  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4065 
4066  /*
4067  * Find or create a lock with this tag.
4068  */
4070  (void *) locktag,
4071  hashcode,
4073  &found);
4074  if (!lock)
4075  {
4076  LWLockRelease(partitionLock);
4077  ereport(ERROR,
4078  (errcode(ERRCODE_OUT_OF_MEMORY),
4079  errmsg("out of shared memory"),
4080  errhint("You might need to increase max_locks_per_transaction.")));
4081  }
4082 
4083  /*
4084  * if it's a new lock object, initialize it
4085  */
4086  if (!found)
4087  {
4088  lock->grantMask = 0;
4089  lock->waitMask = 0;
4090  SHMQueueInit(&(lock->procLocks));
4091  ProcQueueInit(&(lock->waitProcs));
4092  lock->nRequested = 0;
4093  lock->nGranted = 0;
4094  MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4095  MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4096  LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4097  }
4098  else
4099  {
4100  LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4101  Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4102  Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4103  Assert(lock->nGranted <= lock->nRequested);
4104  }
4105 
4106  /*
4107  * Create the hash key for the proclock table.
4108  */
4109  proclocktag.myLock = lock;
4110  proclocktag.myProc = proc;
4111 
4112  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4113 
4114  /*
4115  * Find or create a proclock entry with this tag
4116  */
4118  (void *) &proclocktag,
4119  proclock_hashcode,
4121  &found);
4122  if (!proclock)
4123  {
4124  /* Oops, not enough shmem for the proclock */
4125  if (lock->nRequested == 0)
4126  {
4127  /*
4128  * There are no other requestors of this lock, so garbage-collect
4129  * the lock object. We *must* do this to avoid a permanent leak
4130  * of shared memory, because there won't be anything to cause
4131  * anyone to release the lock object later.
4132  */
4133  Assert(SHMQueueEmpty(&(lock->procLocks)));
4135  (void *) &(lock->tag),
4136  hashcode,
4137  HASH_REMOVE,
4138  NULL))
4139  elog(PANIC, "lock table corrupted");
4140  }
4141  LWLockRelease(partitionLock);
4142  ereport(ERROR,
4143  (errcode(ERRCODE_OUT_OF_MEMORY),
4144  errmsg("out of shared memory"),
4145  errhint("You might need to increase max_locks_per_transaction.")));
4146  }
4147 
4148  /*
4149  * If new, initialize the new entry
4150  */
4151  if (!found)
4152  {
4153  Assert(proc->lockGroupLeader == NULL);
4154  proclock->groupLeader = proc;
4155  proclock->holdMask = 0;
4156  proclock->releaseMask = 0;
4157  /* Add proclock to appropriate lists */
4158  SHMQueueInsertBefore(&lock->procLocks, &proclock->lockLink);
4159  SHMQueueInsertBefore(&(proc->myProcLocks[partition]),
4160  &proclock->procLink);
4161  PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4162  }
4163  else
4164  {
4165  PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4166  Assert((proclock->holdMask & ~lock->grantMask) == 0);
4167  }
4168 
4169  /*
4170  * lock->nRequested and lock->requested[] count the total number of
4171  * requests, whether granted or waiting, so increment those immediately.
4172  */
4173  lock->nRequested++;
4174  lock->requested[lockmode]++;
4175  Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4176 
4177  /*
4178  * We shouldn't already hold the desired lock.
4179  */
4180  if (proclock->holdMask & LOCKBIT_ON(lockmode))
4181  elog(ERROR, "lock %s on object %u/%u/%u is already held",
4182  lockMethodTable->lockModeNames[lockmode],
4183  lock->tag.locktag_field1, lock->tag.locktag_field2,
4184  lock->tag.locktag_field3);
4185 
4186  /*
4187  * We ignore any possible conflicts and just grant ourselves the lock. Not
4188  * only because we don't bother, but also to avoid deadlocks when
4189  * switching from standby to normal mode. See function comment.
4190  */
4191  GrantLock(lock, proclock, lockmode);
4192 
4193  /*
4194  * Bump strong lock count, to make sure any fast-path lock requests won't
4195  * be granted without consulting the primary lock table.
4196  */
4197  if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4198  {
4199  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4200 
4202  FastPathStrongRelationLocks->count[fasthashcode]++;
4204  }
4205 
4206  LWLockRelease(partitionLock);
4207 }
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:974
#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:1467
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:570
#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:1022
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:784
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 4214 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().

4216 {
4217  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4218  LOCKTAG *locktag;
4219  LOCKMODE lockmode;
4220  LOCKMETHODID lockmethodid;
4221 
4222  Assert(len == sizeof(TwoPhaseLockRecord));
4223  locktag = &rec->locktag;
4224  lockmode = rec->lockmode;
4225  lockmethodid = locktag->locktag_lockmethodid;
4226 
4227  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4228  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4229 
4230  if (lockmode == AccessExclusiveLock &&
4231  locktag->locktag_type == LOCKTAG_RELATION)
4232  {
4234  locktag->locktag_field1 /* dboid */ ,
4235  locktag->locktag_field2 /* reloid */ );
4236  }
4237 }
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 732 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().

738 {
739  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
740  LockMethod lockMethodTable;
741  LOCALLOCKTAG localtag;
742  LOCALLOCK *locallock;
743  LOCK *lock;
744  PROCLOCK *proclock;
745  bool found;
746  ResourceOwner owner;
747  uint32 hashcode;
748  LWLock *partitionLock;
749  int status;
750  bool log_lock = false;
751 
752  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
753  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
754  lockMethodTable = LockMethods[lockmethodid];
755  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
756  elog(ERROR, "unrecognized lock mode: %d", lockmode);
757 
758  if (RecoveryInProgress() && !InRecovery &&
759  (locktag->locktag_type == LOCKTAG_OBJECT ||
760  locktag->locktag_type == LOCKTAG_RELATION) &&
761  lockmode > RowExclusiveLock)
762  ereport(ERROR,
763  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
764  errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
765  lockMethodTable->lockModeNames[lockmode]),
766  errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
767 
768 #ifdef LOCK_DEBUG
769  if (LOCK_DEBUG_ENABLED(locktag))
770  elog(LOG, "LockAcquire: lock [%u,%u] %s",
771  locktag->locktag_field1, locktag->locktag_field2,
772  lockMethodTable->lockModeNames[lockmode]);
773 #endif
774 
775  /* Identify owner for lock */
776  if (sessionLock)
777  owner = NULL;
778  else
779  owner = CurrentResourceOwner;
780 
781  /*
782  * Find or create a LOCALLOCK entry for this lock and lockmode
783  */
784  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
785  localtag.lock = *locktag;
786  localtag.mode = lockmode;
787 
788  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
789  (void *) &localtag,
790  HASH_ENTER, &found);
791 
792  /*
793  * if it's a new locallock object, initialize it
794  */
795  if (!found)
796  {
797  locallock->lock = NULL;
798  locallock->proclock = NULL;
799  locallock->hashcode = LockTagHashCode(&(localtag.lock));
800  locallock->nLocks = 0;
801  locallock->holdsStrongLockCount = false;
802  locallock->lockCleared = false;
803  locallock->numLockOwners = 0;
804  locallock->maxLockOwners = 8;
805  locallock->lockOwners = NULL; /* in case next line fails */
806  locallock->lockOwners = (LOCALLOCKOWNER *)
808  locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
809  }
810  else
811  {
812  /* Make sure there will be room to remember the lock */
813  if (locallock->numLockOwners >= locallock->maxLockOwners)
814  {
815  int newsize = locallock->maxLockOwners * 2;
816 
817  locallock->lockOwners = (LOCALLOCKOWNER *)
818  repalloc(locallock->lockOwners,
819  newsize * sizeof(LOCALLOCKOWNER));
820  locallock->maxLockOwners = newsize;
821  }
822  }
823  hashcode = locallock->hashcode;
824 
825  if (locallockp)
826  *locallockp = locallock;
827 
828  /*
829  * If we already hold the lock, we can just increase the count locally.
830  *
831  * If lockCleared is already set, caller need not worry about absorbing
832  * sinval messages related to the lock's object.
833  */
834  if (locallock->nLocks > 0)
835  {
836  GrantLockLocal(locallock, owner);
837  if (locallock->lockCleared)
839  else
841  }
842 
843  /*
844  * Prepare to emit a WAL record if acquisition of this lock needs to be
845  * replayed in a standby server.
846  *
847  * Here we prepare to log; after lock is acquired we'll issue log record.
848  * This arrangement simplifies error recovery in case the preparation step
849  * fails.
850  *
851  * Only AccessExclusiveLocks can conflict with lock types that read-only
852  * transactions can acquire in a standby server. Make sure this definition
853  * matches the one in GetRunningTransactionLocks().
854  */
855  if (lockmode >= AccessExclusiveLock &&
856  locktag->locktag_type == LOCKTAG_RELATION &&
857  !RecoveryInProgress() &&
859  {
861  log_lock = true;
862  }
863 
864  /*
865  * Attempt to take lock via fast path, if eligible. But if we remember
866  * having filled up the fast path array, we don't attempt to make any
867  * further use of it until we release some locks. It's possible that some
868  * other backend has transferred some of those locks to the shared hash
869  * table, leaving space free, but it's not worth acquiring the LWLock just
870  * to check. It's also possible that we're acquiring a second or third
871  * lock type on a relation we have already locked using the fast-path, but
872  * for now we don't worry about that case either.
873  */
874  if (EligibleForRelationFastPath(locktag, lockmode) &&
876  {
877  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
878  bool acquired;
879 
880  /*
881  * LWLockAcquire acts as a memory sequencing point, so it's safe to
882  * assume that any strong locker whose increment to
883  * FastPathStrongRelationLocks->counts becomes visible after we test
884  * it has yet to begin to transfer fast-path locks.
885  */
887  if (FastPathStrongRelationLocks->count[fasthashcode] != 0)
888  acquired = false;
889  else
890  acquired = FastPathGrantRelationLock(locktag->locktag_field2,
891  lockmode);
893  if (acquired)
894  {
895  /*
896  * The locallock might contain stale pointers to some old shared
897  * objects; we MUST reset these to null before considering the
898  * lock to be acquired via fast-path.
899  */
900  locallock->lock = NULL;
901  locallock->proclock = NULL;
902  GrantLockLocal(locallock, owner);
903  return LOCKACQUIRE_OK;
904  }
905  }
906 
907  /*
908  * If this lock could potentially have been taken via the fast-path by
909  * some other backend, we must (temporarily) disable further use of the
910  * fast-path for this lock tag, and migrate any locks already taken via
911  * this method to the main lock table.
912  */
913  if (ConflictsWithRelationFastPath(locktag, lockmode))
914  {
915  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
916 
917  BeginStrongLockAcquire(locallock, fasthashcode);
918  if (!FastPathTransferRelationLocks(lockMethodTable, locktag,
919  hashcode))
920  {
922  if (locallock->nLocks == 0)
923  RemoveLocalLock(locallock);
924  if (locallockp)
925  *locallockp = NULL;
926  if (reportMemoryError)
927  ereport(ERROR,
928  (errcode(ERRCODE_OUT_OF_MEMORY),
929  errmsg("out of shared memory"),
930  errhint("You might need to increase max_locks_per_transaction.")));
931  else
932  return LOCKACQUIRE_NOT_AVAIL;
933  }
934  }
935 
936  /*
937  * We didn't find the lock in our LOCALLOCK table, and we didn't manage to
938  * take it via the fast-path, either, so we've got to mess with the shared
939  * lock table.
940  */
941  partitionLock = LockHashPartitionLock(hashcode);
942 
943  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
944 
945  /*
946  * Find or create lock and proclock entries with this tag
947  *
948  * Note: if the locallock object already existed, it might have a pointer
949  * to the lock already ... but we should not assume that that pointer is
950  * valid, since a lock object with zero hold and request counts can go
951  * away anytime. So we have to use SetupLockInTable() to recompute the
952  * lock and proclock pointers, even if they're already set.
953  */
954  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
955  hashcode, lockmode);
956  if (!proclock)
957  {
959  LWLockRelease(partitionLock);
960  if (locallock->nLocks == 0)
961  RemoveLocalLock(locallock);
962  if (locallockp)
963  *locallockp = NULL;
964  if (reportMemoryError)
965  ereport(ERROR,
966  (errcode(ERRCODE_OUT_OF_MEMORY),
967  errmsg("out of shared memory"),
968  errhint("You might need to increase max_locks_per_transaction.")));
969  else
970  return LOCKACQUIRE_NOT_AVAIL;
971  }
972  locallock->proclock = proclock;
973  lock = proclock->tag.myLock;
974  locallock->lock = lock;
975 
976  /*
977  * If lock requested conflicts with locks requested by waiters, must join
978  * wait queue. Otherwise, check for conflict with already-held locks.
979  * (That's last because most complex check.)
980  */
981  if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
982  status = STATUS_FOUND;
983  else
984  status = LockCheckConflicts(lockMethodTable, lockmode,
985  lock, proclock);
986 
987  if (status == STATUS_OK)
988  {
989  /* No conflict with held or previously requested locks */
990  GrantLock(lock, proclock, lockmode);
991  GrantLockLocal(locallock, owner);
992  }
993  else
994  {
995  Assert(status == STATUS_FOUND);
996 
997  /*
998  * We can't acquire the lock immediately. If caller specified no
999  * blocking, remove useless table entries and return NOT_AVAIL without
1000  * waiting.
1001  */
1002  if (dontWait)
1003  {
1005  if (proclock->holdMask == 0)
1006  {
1007  uint32 proclock_hashcode;
1008 
1009  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
1010  SHMQueueDelete(&proclock->lockLink);
1011  SHMQueueDelete(&proclock->procLink);
1013  (void *) &(proclock->tag),
1014  proclock_hashcode,
1015  HASH_REMOVE,
1016  NULL))
1017  elog(PANIC, "proclock table corrupted");
1018  }
1019  else
1020  PROCLOCK_PRINT("LockAcquire: NOWAIT", proclock);
1021  lock->nRequested--;
1022  lock->requested[lockmode]--;
1023  LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
1024  Assert((lock->nRequested > 0) && (lock->requested[lockmode] >= 0));
1025  Assert(lock->nGranted <= lock->nRequested);
1026  LWLockRelease(partitionLock);
1027  if (locallock->nLocks == 0)
1028  RemoveLocalLock(locallock);
1029  if (locallockp)
1030  *locallockp = NULL;
1031  return LOCKACQUIRE_NOT_AVAIL;
1032  }
1033 
1034  /*
1035  * Set bitmask of locks this process already holds on this object.
1036  */
1037  MyProc->heldLocks = proclock->holdMask;
1038 
1039  /*
1040  * Sleep till someone wakes me up.
1041  */
1042 
1043  TRACE_POSTGRESQL_LOCK_WAIT_START(locktag->locktag_field1,
1044  locktag->locktag_field2,
1045  locktag->locktag_field3,
1046  locktag->locktag_field4,
1047  locktag->locktag_type,
1048  lockmode);
1049 
1050  WaitOnLock(locallock, owner);
1051 
1052  TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
1053  locktag->locktag_field2,
1054  locktag->locktag_field3,
1055  locktag->locktag_field4,
1056  locktag->locktag_type,
1057  lockmode);
1058 
1059  /*
1060  * NOTE: do not do any material change of state between here and
1061  * return. All required changes in locktable state must have been
1062  * done when the lock was granted to us --- see notes in WaitOnLock.
1063  */
1064 
1065  /*
1066  * Check the proclock entry status, in case something in the ipc
1067  * communication doesn't work correctly.
1068  */
1069  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
1070  {
1072  PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
1073  LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
1074  /* Should we retry ? */
1075  LWLockRelease(partitionLock);
1076  elog(ERROR, "LockAcquire failed");
1077  }
1078  PROCLOCK_PRINT("LockAcquire: granted", proclock);
1079  LOCK_PRINT("LockAcquire: granted", lock, lockmode);
1080  }
1081 
1082  /*
1083  * Lock state is fully up-to-date now; if we error out after this, no
1084  * special error cleanup is required.
1085  */
1087 
1088  LWLockRelease(partitionLock);
1089 
1090  /*
1091  * Emit a WAL record if acquisition of this lock needs to be replayed in a
1092  * standby server.
1093  */
1094  if (log_lock)
1095  {
1096  /*
1097  * Decode the locktag back to the original values, to avoid sending
1098  * lots of empty bytes with every message. See lock.h to check how a
1099  * locktag is defined for LOCKTAG_RELATION
1100  */
1102  locktag->locktag_field2);
1103  }
1104 
1105  return LOCKACQUIRE_OK;
1106 }
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:1344
static HTAB * LockMethodLocalHash
Definition: lock.c:255
bool holdsStrongLockCount
Definition: lock.h:411
int errhint(const char *fmt,...)
Definition: elog.c:974
int numLockOwners
Definition: lock.h:413
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1119
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
LOCKTAG lock
Definition: lock.h:385
static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2564
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:1467
ResourceOwner CurrentResourceOwner
Definition: resowner.c:141
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
bool InRecovery
Definition: xlog.c:188
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:570
#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:8065
#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:1723
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:1296
static void FinishStrongLockAcquire(void)
Definition: lock.c:1656
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:1666
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:1075
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:1630
#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:1078
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:784
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:2631
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:1601
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 1344 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().

1348 {
1349  int numLockModes = lockMethodTable->numLockModes;
1350  LOCKMASK myLocks;
1351  int conflictMask = lockMethodTable->conflictTab[lockmode];
1352  int conflictsRemaining[MAX_LOCKMODES];
1353  int totalConflictsRemaining = 0;
1354  int i;
1355  SHM_QUEUE *procLocks;
1356  PROCLOCK *otherproclock;
1357 
1358  /*
1359  * first check for global conflicts: If no locks conflict with my request,
1360  * then I get the lock.
1361  *
1362  * Checking for conflict: lock->grantMask represents the types of
1363  * currently held locks. conflictTable[lockmode] has a bit set for each
1364  * type of lock that conflicts with request. Bitwise compare tells if
1365  * there is a conflict.
1366  */
1367  if (!(conflictMask & lock->grantMask))
1368  {
1369  PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1370  return STATUS_OK;
1371  }
1372 
1373  /*
1374  * Rats. Something conflicts. But it could still be my own lock, or a
1375  * lock held by another member of my locking group. First, figure out how
1376  * many conflicts remain after subtracting out any locks I hold myself.
1377  */
1378  myLocks = proclock->holdMask;
1379  for (i = 1; i <= numLockModes; i++)
1380  {
1381  if ((conflictMask & LOCKBIT_ON(i)) == 0)
1382  {
1383  conflictsRemaining[i] = 0;
1384  continue;
1385  }
1386  conflictsRemaining[i] = lock->granted[i];
1387  if (myLocks & LOCKBIT_ON(i))
1388  --conflictsRemaining[i];
1389  totalConflictsRemaining += conflictsRemaining[i];
1390  }
1391 
1392  /* If no conflicts remain, we get the lock. */
1393  if (totalConflictsRemaining == 0)
1394  {
1395  PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1396  return STATUS_OK;
1397  }
1398 
1399  /* If no group locking, it's definitely a conflict. */
1400  if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL)
1401  {
1402  Assert(proclock->tag.myProc == MyProc);
1403  PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1404  proclock);
1405  return STATUS_FOUND;
1406  }
1407 
1408  /*
1409  * Locks held in conflicting modes by members of our own lock group are
1410  * not real conflicts; we can subtract those out and see if we still have
1411  * a conflict. This is O(N) in the number of processes holding or
1412  * awaiting locks on this object. We could improve that by making the
1413  * shared memory state more complex (and larger) but it doesn't seem worth
1414  * it.
1415  */
1416  procLocks = &(lock->procLocks);
1417  otherproclock = (PROCLOCK *)
1418  SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink));
1419  while (otherproclock != NULL)
1420  {
1421  if (proclock != otherproclock &&
1422  proclock->groupLeader == otherproclock->groupLeader &&
1423  (otherproclock->holdMask & conflictMask) != 0)
1424  {
1425  int intersectMask = otherproclock->holdMask & conflictMask;
1426 
1427  for (i = 1; i <= numLockModes; i++)
1428  {
1429  if ((intersectMask & LOCKBIT_ON(i)) != 0)
1430  {
1431  if (conflictsRemaining[i] <= 0)
1432  elog(PANIC, "proclocks held do not match lock");
1433  conflictsRemaining[i]--;
1434  totalConflictsRemaining--;
1435  }
1436  }
1437 
1438  if (totalConflictsRemaining == 0)
1439  {
1440  PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1441  proclock);
1442  return STATUS_OK;
1443  }
1444  }
1445  otherproclock = (PROCLOCK *)
1446  SHMQueueNext(procLocks, &otherproclock->lockLink,
1447  offsetof(PROCLOCK, lockLink));
1448  }
1449 
1450  /* Nope, it's a real conflict. */
1451  PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1452  return STATUS_FOUND;
1453 }
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:1075
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:1078
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 595 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().

596 {
597  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
598  LockMethod lockMethodTable;
599  LOCALLOCKTAG localtag;
600  LOCALLOCK *locallock;
601  LOCK *lock;
602  PROCLOCK *proclock;
603  LWLock *partitionLock;
604  bool hasWaiters = false;
605 
606  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
607  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
608  lockMethodTable = LockMethods[lockmethodid];
609  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
610  elog(ERROR, "unrecognized lock mode: %d", lockmode);
611 
612 #ifdef LOCK_DEBUG
613  if (LOCK_DEBUG_ENABLED(locktag))
614  elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
615  locktag->locktag_field1, locktag->locktag_field2,
616  lockMethodTable->lockModeNames[lockmode]);
617 #endif
618 
619  /*
620  * Find the LOCALLOCK entry for this lock and lockmode
621  */
622  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
623  localtag.lock = *locktag;
624  localtag.mode = lockmode;
625 
626  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
627  (void *) &localtag,
628  HASH_FIND, NULL);
629 
630  /*
631  * let the caller print its own error message, too. Do not ereport(ERROR).
632  */
633  if (!locallock || locallock->nLocks <= 0)
634  {
635  elog(WARNING, "you don't own a lock of type %s",
636  lockMethodTable->lockModeNames[lockmode]);
637  return false;
638  }
639 
640  /*
641  * Check the shared lock table.
642  */
643  partitionLock = LockHashPartitionLock(locallock->hashcode);
644 
645  LWLockAcquire(partitionLock, LW_SHARED);
646 
647  /*
648  * We don't need to re-find the lock or proclock, since we kept their
649  * addresses in the locallock table, and they couldn't have been removed
650  * while we were holding a lock on them.
651  */
652  lock = locallock->lock;
653  LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
654  proclock = locallock->proclock;
655  PROCLOCK_PRINT("LockHasWaiters: found", proclock);
656 
657  /*
658  * Double-check that we are actually holding a lock of the type we want to
659  * release.
660  */
661  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
662  {
663  PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
664  LWLockRelease(partitionLock);
665  elog(WARNING, "you don't own a lock of type %s",
666  lockMethodTable->lockModeNames[lockmode]);
667  RemoveLocalLock(locallock);
668  return false;
669  }
670 
671  /*
672  * Do the checking.
673  */
674  if ((lockMethodTable->conflictTab[lockmode] & lock->waitMask) != 0)
675  hasWaiters = true;
676 
677  LWLockRelease(partitionLock);
678 
679  return hasWaiters;
680 }
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:1296
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

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 571 of file lock.c.

References HASH_FIND, hash_search(), LOCALLOCKTAG::lock, TwoPhaseLockRecord::lockmode, TwoPhaseLockRecord::locktag, MemSet, LOCALLOCKTAG::mode, and LOCALLOCK::nLocks.

Referenced by CheckRelationLockedByMe().

572 {
573  LOCALLOCKTAG localtag;
574  LOCALLOCK *locallock;
575 
576  /*
577  * See if there is a LOCALLOCK entry for this lock and lockmode
578  */
579  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
580  localtag.lock = *locktag;
581  localtag.mode = lockmode;
582 
583  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
584  (void *) &localtag,
585  HASH_FIND, NULL);
586 
587  return (locallock && locallock->nLocks > 0);
588 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
#define MemSet(start, val, len)
Definition: c.h:941
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
int64 nLocks
Definition: lock.h:410

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2488 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2489 {
2491 
2492  Assert(parent != NULL);
2493 
2494  if (locallocks == NULL)
2495  {
2497  LOCALLOCK *locallock;
2498 
2500 
2501  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2502  LockReassignOwner(locallock, parent);
2503  }
2504  else
2505  {
2506  int i;
2507 
2508  for (i = nlocks - 1; i >= 0; i--)
2509  LockReassignOwner(locallocks[i], parent);
2510  }
2511 }
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2518
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 1884 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().

1885 {
1886  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
1887  LockMethod lockMethodTable;
1888  LOCALLOCKTAG localtag;
1889  LOCALLOCK *locallock;
1890  LOCK *lock;
1891  PROCLOCK *proclock;
1892  LWLock *partitionLock;
1893  bool wakeupNeeded;
1894 
1895  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
1896  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
1897  lockMethodTable = LockMethods[lockmethodid];
1898  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
1899  elog(ERROR, "unrecognized lock mode: %d", lockmode);
1900 
1901 #ifdef LOCK_DEBUG
1902  if (LOCK_DEBUG_ENABLED(locktag))
1903  elog(LOG, "LockRelease: lock [%u,%u] %s",
1904  locktag->locktag_field1, locktag->locktag_field2,
1905  lockMethodTable->lockModeNames[lockmode]);
1906 #endif
1907 
1908  /*
1909  * Find the LOCALLOCK entry for this lock and lockmode
1910  */
1911  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
1912  localtag.lock = *locktag;
1913  localtag.mode = lockmode;
1914 
1915  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
1916  (void *) &localtag,
1917  HASH_FIND, NULL);
1918 
1919  /*
1920  * let the caller print its own error message, too. Do not ereport(ERROR).
1921  */
1922  if (!locallock || locallock->nLocks <= 0)
1923  {
1924  elog(WARNING, "you don't own a lock of type %s",
1925  lockMethodTable->lockModeNames[lockmode]);
1926  return false;
1927  }
1928 
1929  /*
1930  * Decrease the count for the resource owner.
1931  */
1932  {
1933  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1934  ResourceOwner owner;
1935  int i;
1936 
1937  /* Identify owner for lock */
1938  if (sessionLock)
1939  owner = NULL;
1940  else
1941  owner = CurrentResourceOwner;
1942 
1943  for (i = locallock->numLockOwners - 1; i >= 0; i--)
1944  {
1945  if (lockOwners[i].owner == owner)
1946  {
1947  Assert(lockOwners[i].nLocks > 0);
1948  if (--lockOwners[i].nLocks == 0)
1949  {
1950  if (owner != NULL)
1951  ResourceOwnerForgetLock(owner, locallock);
1952  /* compact out unused slot */
1953  locallock->numLockOwners--;
1954  if (i < locallock->numLockOwners)
1955  lockOwners[i] = lockOwners[locallock->numLockOwners];
1956  }
1957  break;
1958  }
1959  }
1960  if (i < 0)
1961  {
1962  /* don't release a lock belonging to another owner */
1963  elog(WARNING, "you don't own a lock of type %s",
1964  lockMethodTable->lockModeNames[lockmode]);
1965  return false;
1966  }
1967  }
1968 
1969  /*
1970  * Decrease the total local count. If we're still holding the lock, we're
1971  * done.
1972  */
1973  locallock->nLocks--;
1974 
1975  if (locallock->nLocks > 0)
1976  return true;
1977 
1978  /*
1979  * At this point we can no longer suppose we are clear of invalidation
1980  * messages related to this lock. Although we'll delete the LOCALLOCK
1981  * object before any intentional return from this routine, it seems worth
1982  * the trouble to explicitly reset lockCleared right now, just in case
1983  * some error prevents us from deleting the LOCALLOCK.
1984  */
1985  locallock->lockCleared = false;
1986 
1987  /* Attempt fast release of any lock eligible for the fast path. */
1988  if (EligibleForRelationFastPath(locktag, lockmode) &&
1990  {
1991  bool released;
1992 
1993  /*
1994  * We might not find the lock here, even if we originally entered it
1995  * here. Another backend may have moved it to the main table.
1996  */
1998  released = FastPathUnGrantRelationLock(locktag->locktag_field2,
1999  lockmode);
2001  if (released)
2002  {
2003  RemoveLocalLock(locallock);
2004  return true;
2005  }
2006  }
2007 
2008  /*
2009  * Otherwise we've got to mess with the shared lock table.
2010  */
2011  partitionLock = LockHashPartitionLock(locallock->hashcode);
2012 
2013  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2014 
2015  /*
2016  * Normally, we don't need to re-find the lock or proclock, since we kept
2017  * their addresses in the locallock table, and they couldn't have been
2018  * removed while we were holding a lock on them. But it's possible that
2019  * the lock was taken fast-path and has since been moved to the main hash
2020  * table by another backend, in which case we will need to look up the
2021  * objects here. We assume the lock field is NULL if so.
2022  */
2023  lock = locallock->lock;
2024  if (!lock)
2025  {
2026  PROCLOCKTAG proclocktag;
2027 
2028  Assert(EligibleForRelationFastPath(locktag, lockmode));
2030  (const void *) locktag,
2031  locallock->hashcode,
2032  HASH_FIND,
2033  NULL);
2034  if (!lock)
2035  elog(ERROR, "failed to re-find shared lock object");
2036  locallock->lock = lock;
2037 
2038  proclocktag.myLock = lock;
2039  proclocktag.myProc = MyProc;
2041  (void *) &proclocktag,
2042  HASH_FIND,
2043  NULL);
2044  if (!locallock->proclock)
2045  elog(ERROR, "failed to re-find shared proclock object");
2046  }
2047  LOCK_PRINT("LockRelease: found", lock, lockmode);
2048  proclock = locallock->proclock;
2049  PROCLOCK_PRINT("LockRelease: found", proclock);
2050 
2051  /*
2052  * Double-check that we are actually holding a lock of the type we want to
2053  * release.
2054  */
2055  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2056  {
2057  PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
2058  LWLockRelease(partitionLock);
2059  elog(WARNING, "you don't own a lock of type %s",
2060  lockMethodTable->lockModeNames[lockmode]);
2061  RemoveLocalLock(locallock);
2062  return false;
2063  }
2064 
2065  /*
2066  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2067  */
2068  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2069 
2070  CleanUpLock(lock, proclock,
2071  lockMethodTable, locallock->hashcode,
2072  wakeupNeeded);
2073 
2074  LWLockRelease(partitionLock);
2075 
2076  RemoveLocalLock(locallock);
2077  return true;
2078 }
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:2601
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:1296
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:1490
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:1547
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 2089 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().

2090 {
2092  LockMethod lockMethodTable;
2093  int i,
2094  numLockModes;
2095  LOCALLOCK *locallock;
2096  LOCK *lock;
2097  PROCLOCK *proclock;
2098  int partition;
2099  bool have_fast_path_lwlock = false;
2100 
2101  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2102  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2103  lockMethodTable = LockMethods[lockmethodid];
2104 
2105 #ifdef LOCK_DEBUG
2106  if (*(lockMethodTable->trace_flag))
2107  elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2108 #endif
2109 
2110  /*
2111  * Get rid of our fast-path VXID lock, if appropriate. Note that this is
2112  * the only way that the lock we hold on our own VXID can ever get
2113  * released: it is always and only released when a toplevel transaction
2114  * ends.
2115  */
2116  if (lockmethodid == DEFAULT_LOCKMETHOD)
2118 
2119  numLockModes = lockMethodTable->numLockModes;
2120 
2121  /*
2122  * First we run through the locallock table and get rid of unwanted
2123  * entries, then we scan the process's proclocks and get rid of those. We
2124  * do this separately because we may have multiple locallock entries
2125  * pointing to the same proclock, and we daren't end up with any dangling
2126  * pointers. Fast-path locks are cleaned up during the locallock table
2127  * scan, though.
2128  */
2130 
2131  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2132  {
2133  /*
2134  * If the LOCALLOCK entry is unused, we must've run out of shared
2135  * memory while trying to set up this lock. Just forget the local
2136  * entry.
2137  */
2138  if (locallock->nLocks == 0)
2139  {
2140  RemoveLocalLock(locallock);
2141  continue;
2142  }
2143 
2144  /* Ignore items that are not of the lockmethod to be removed */
2145  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2146  continue;
2147 
2148  /*
2149  * If we are asked to release all locks, we can just zap the entry.
2150  * Otherwise, must scan to see if there are session locks. We assume
2151  * there is at most one lockOwners entry for session locks.
2152  */
2153  if (!allLocks)
2154  {
2155  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2156 
2157  /* If session lock is above array position 0, move it down to 0 */
2158  for (i = 0; i < locallock->numLockOwners; i++)
2159  {
2160  if (lockOwners[i].owner == NULL)
2161  lockOwners[0] = lockOwners[i];
2162  else
2163  ResourceOwnerForgetLock(lockOwners[i].owner, locallock);
2164  }
2165 
2166  if (locallock->numLockOwners > 0 &&
2167  lockOwners[0].owner == NULL &&
2168  lockOwners[0].nLocks > 0)
2169  {
2170  /* Fix the locallock to show just the session locks */
2171  locallock->nLocks = lockOwners[0].nLocks;
2172  locallock->numLockOwners = 1;
2173  /* We aren't deleting this locallock, so done */
2174  continue;
2175  }
2176  else
2177  locallock->numLockOwners = 0;
2178  }
2179 
2180  /*
2181  * If the lock or proclock pointers are NULL, this lock was taken via
2182  * the relation fast-path (and is not known to have been transferred).
2183  */
2184  if (locallock->proclock == NULL || locallock->lock == NULL)
2185  {
2186  LOCKMODE lockmode = locallock->tag.mode;
2187  Oid relid;
2188 
2189  /* Verify that a fast-path lock is what we've got. */
2190  if (!EligibleForRelationFastPath(&locallock->tag.lock, lockmode))
2191  elog(PANIC, "locallock table corrupted");
2192 
2193  /*
2194  * If we don't currently hold the LWLock that protects our
2195  * fast-path data structures, we must acquire it before attempting
2196  * to release the lock via the fast-path. We will continue to
2197  * hold the LWLock until we're done scanning the locallock table,
2198  * unless we hit a transferred fast-path lock. (XXX is this
2199  * really such a good idea? There could be a lot of entries ...)
2200  */
2201  if (!have_fast_path_lwlock)
2202  {
2204  have_fast_path_lwlock = true;
2205  }
2206 
2207  /* Attempt fast-path release. */
2208  relid = locallock->tag.lock.locktag_field2;
2209  if (FastPathUnGrantRelationLock(relid, lockmode))
2210  {
2211  RemoveLocalLock(locallock);
2212  continue;
2213  }
2214 
2215  /*
2216  * Our lock, originally taken via the fast path, has been
2217  * transferred to the main lock table. That's going to require
2218  * some extra work, so release our fast-path lock before starting.
2219  */
2221  have_fast_path_lwlock = false;
2222 
2223  /*
2224  * Now dump the lock. We haven't got a pointer to the LOCK or
2225  * PROCLOCK in this case, so we have to handle this a bit
2226  * differently than a normal lock release. Unfortunately, this
2227  * requires an extra LWLock acquire-and-release cycle on the
2228  * partitionLock, but hopefully it shouldn't happen often.
2229  */
2230  LockRefindAndRelease(lockMethodTable, MyProc,
2231  &locallock->tag.lock, lockmode, false);
2232  RemoveLocalLock(locallock);
2233  continue;
2234  }
2235 
2236  /* Mark the proclock to show we need to release this lockmode */
2237  if (locallock->nLocks > 0)
2238  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
2239 
2240  /* And remove the locallock hashtable entry */
2241  RemoveLocalLock(locallock);
2242  }
2243 
2244  /* Done with the fast-path data structures */
2245  if (have_fast_path_lwlock)
2247 
2248  /*
2249  * Now, scan each lock partition separately.
2250  */
2251  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
2252  {
2253  LWLock *partitionLock;
2254  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
2255  PROCLOCK *nextplock;
2256 
2257  partitionLock = LockHashPartitionLockByIndex(partition);
2258 
2259  /*
2260  * If the proclock list for this partition is empty, we can skip
2261  * acquiring the partition lock. This optimization is trickier than
2262  * it looks, because another backend could be in process of adding
2263  * something to our proclock list due to promoting one of our
2264  * fast-path locks. However, any such lock must be one that we
2265  * decided not to delete above, so it's okay to skip it again now;
2266  * we'd just decide not to delete it again. We must, however, be
2267  * careful to re-fetch the list header once we've acquired the
2268  * partition lock, to be sure we have a valid, up-to-date pointer.
2269  * (There is probably no significant risk if pointer fetch/store is
2270  * atomic, but we don't wish to assume that.)
2271  *
2272  * XXX This argument assumes that the locallock table correctly
2273  * represents all of our fast-path locks. While allLocks mode
2274  * guarantees to clean up all of our normal locks regardless of the
2275  * locallock situation, we lose that guarantee for fast-path locks.
2276  * This is not ideal.
2277  */
2278  if (SHMQueueNext(procLocks, procLocks,
2279  offsetof(PROCLOCK, procLink)) == NULL)
2280  continue; /* needn't examine this partition */
2281 
2282  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2283 
2284  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2285  offsetof(PROCLOCK, procLink));
2286  proclock;
2287  proclock = nextplock)
2288  {
2289  bool wakeupNeeded = false;
2290 
2291  /* Get link first, since we may unlink/delete this proclock */
2292  nextplock = (PROCLOCK *)
2293  SHMQueueNext(procLocks, &proclock->procLink,
2294  offsetof(PROCLOCK, procLink));
2295 
2296  Assert(proclock->tag.myProc == MyProc);
2297 
2298  lock = proclock->tag.myLock;
2299 
2300  /* Ignore items that are not of the lockmethod to be removed */
2301  if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
2302  continue;
2303 
2304  /*
2305  * In allLocks mode, force release of all locks even if locallock
2306  * table had problems
2307  */
2308  if (allLocks)
2309  proclock->releaseMask = proclock->holdMask;
2310  else
2311  Assert((proclock->releaseMask & ~proclock->holdMask) == 0);
2312 
2313  /*
2314  * Ignore items that have nothing to be released, unless they have
2315  * holdMask == 0 and are therefore recyclable
2316  */
2317  if (proclock->releaseMask == 0 && proclock->holdMask != 0)
2318  continue;
2319 
2320  PROCLOCK_PRINT("LockReleaseAll", proclock);
2321  LOCK_PRINT("LockReleaseAll", lock, 0);
2322  Assert(lock->nRequested >= 0);
2323  Assert(lock->nGranted >= 0);
2324  Assert(lock->nGranted <= lock->nRequested);
2325  Assert((proclock->holdMask & ~lock->grantMask) == 0);
2326 
2327  /*
2328  * Release the previously-marked lock modes
2329  */
2330  for (i = 1; i <= numLockModes; i++)
2331  {
2332  if (proclock->releaseMask & LOCKBIT_ON(i))
2333  wakeupNeeded |= UnGrantLock(lock, i, proclock,
2334  lockMethodTable);
2335  }
2336  Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
2337  Assert(lock->nGranted <= lock->nRequested);
2338  LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2339 
2340  proclock->releaseMask = 0;
2341 
2342  /* CleanUpLock will wake up waiters if needed. */
2343  CleanUpLock(lock, proclock,
2344  lockMethodTable,
2345  LockTagHashCode(&lock->tag),
2346  wakeupNeeded);
2347  } /* loop over PROCLOCKs within this partition */
2348 
2349  LWLockRelease(partitionLock);
2350  } /* loop over partitions */
2351 
2352 #ifdef LOCK_DEBUG
2353  if (*(lockMethodTable->trace_flag))
2354  elog(LOG, "LockReleaseAll done");
2355 #endif
2356 }
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:3037
void VirtualXactLockTableCleanup(void)
Definition: lock.c:4319
int numLockOwners
Definition: lock.h:413
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2601
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:1296
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:1490
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:1547
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 2393 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2394 {
2395  if (locallocks == NULL)
2396  {
2398  LOCALLOCK *locallock;
2399 
2401 
2402  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2403  ReleaseLockIfHeld(locallock, false);
2404  }
2405  else
2406  {
2407  int i;
2408 
2409  for (i = nlocks - 1; i >= 0; i--)
2410  ReleaseLockIfHeld(locallocks[i], false);
2411  }
2412 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2428
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 2363 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().

2364 {
2366  LOCALLOCK *locallock;
2367 
2368  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2369  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2370 
2372 
2373  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2374  {
2375  /* Ignore items that are not of the specified lock method */
2376  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2377  continue;
2378 
2379  ReleaseLockIfHeld(locallock, true);
2380  }
2381 }
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:2428
#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 3436 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

3437 {
3438  Size size = 0;
3439  long max_table_size;
3440 
3441  /* lock hash table */
3442  max_table_size = NLOCKENTS();
3443  size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3444 
3445  /* proclock hash table */
3446  max_table_size *= 2;
3447  size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3448 
3449  /*
3450  * Since NLOCKENTS is only an estimate, add 10% safety margin.
3451  */
3452  size = add_size(size, size / 10);
3453 
3454  return size;
3455 }
#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 4462 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().

4463 {
4464  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4465  LOCK *lock;
4466  bool found;
4467  uint32 hashcode;
4468  LWLock *partitionLock;
4469  int waiters = 0;
4470 
4471  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4472  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4473 
4474  hashcode = LockTagHashCode(locktag);
4475  partitionLock = LockHashPartitionLock(hashcode);
4476  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4477 
4479  (const void *) locktag,
4480  hashcode,
4481  HASH_FIND,
4482  &found);
4483  if (found)
4484  {
4485  Assert(lock != NULL);
4486  waiters = lock->nRequested;
4487  }
4488  LWLockRelease(partitionLock);
4489 
4490  return waiters;
4491 }
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 1708 of file lock.c.

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

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

1709 {
1710  Assert(locallock->nLocks > 0);
1711  locallock->lockCleared = true;
1712 }
#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 3244 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().

3245 {
3246  PGPROC *newproc = TwoPhaseGetDummyProc(xid);
3248  LOCALLOCK *locallock;
3249  LOCK *lock;
3250  PROCLOCK *proclock;
3251  PROCLOCKTAG proclocktag;
3252  int partition;
3253 
3254  /* Can't prepare a lock group follower. */
3255  Assert(MyProc->lockGroupLeader == NULL ||
3257 
3258  /* This is a critical section: any error means big trouble */
3260 
3261  /*
3262  * First we run through the locallock table and get rid of unwanted
3263  * entries, then we scan the process's proclocks and transfer them to the
3264  * target proc.
3265  *
3266  * We do this separately because we may have multiple locallock entries
3267  * pointing to the same proclock, and we daren't end up with any dangling
3268  * pointers.
3269  */
3271 
3272  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3273  {
3274  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3275  bool haveSessionLock;
3276  bool haveXactLock;
3277  int i;
3278 
3279  if (locallock->proclock == NULL || locallock->lock == NULL)
3280  {
3281  /*
3282  * We must've run out of shared memory while trying to set up this
3283  * lock. Just forget the local entry.
3284  */
3285  Assert(locallock->nLocks == 0);
3286  RemoveLocalLock(locallock);
3287  continue;
3288  }
3289 
3290  /* Ignore VXID locks */
3291  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3292  continue;
3293 
3294  /* Scan to see whether we hold it at session or transaction level */
3295  haveSessionLock = haveXactLock = false;
3296  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3297  {
3298  if (lockOwners[i].owner == NULL)
3299  haveSessionLock = true;
3300  else
3301  haveXactLock = true;
3302  }
3303 
3304  /* Ignore it if we have only session lock */
3305  if (!haveXactLock)
3306  continue;
3307 
3308  /* This can't happen, because we already checked it */
3309  if (haveSessionLock)
3310  ereport(PANIC,
3311  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3312  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3313 
3314  /* Mark the proclock to show we need to release this lockmode */
3315  if (locallock->nLocks > 0)
3316  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3317 
3318  /* And remove the locallock hashtable entry */
3319  RemoveLocalLock(locallock);
3320  }
3321 
3322  /*
3323  * Now, scan each lock partition separately.
3324  */
3325  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3326  {
3327  LWLock *partitionLock;
3328  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
3329  PROCLOCK *nextplock;
3330 
3331  partitionLock = LockHashPartitionLockByIndex(partition);
3332 
3333  /*
3334  * If the proclock list for this partition is empty, we can skip
3335  * acquiring the partition lock. This optimization is safer than the
3336  * situation in LockReleaseAll, because we got rid of any fast-path
3337  * locks during AtPrepare_Locks, so there cannot be any case where
3338  * another backend is adding something to our lists now. For safety,
3339  * though, we code this the same way as in LockReleaseAll.
3340  */
3341  if (SHMQueueNext(procLocks, procLocks,
3342  offsetof(PROCLOCK, procLink)) == NULL)
3343  continue; /* needn't examine this partition */
3344 
3345  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3346 
3347  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3348  offsetof(PROCLOCK, procLink));
3349  proclock;
3350  proclock = nextplock)
3351  {
3352  /* Get link first, since we may unlink/relink this proclock */
3353  nextplock = (PROCLOCK *)
3354  SHMQueueNext(procLocks, &proclock->procLink,
3355  offsetof(PROCLOCK, procLink));
3356 
3357  Assert(proclock->tag.myProc == MyProc);
3358 
3359  lock = proclock->tag.myLock;
3360 
3361  /* Ignore VXID locks */
3363  continue;
3364 
3365  PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3366  LOCK_PRINT("PostPrepare_Locks", lock, 0);
3367  Assert(lock->nRequested >= 0);
3368  Assert(lock->nGranted >= 0);
3369  Assert(lock->nGranted <= lock->nRequested);
3370  Assert((proclock->holdMask & ~lock->grantMask) == 0);
3371 
3372  /* Ignore it if nothing to release (must be a session lock) */
3373  if (proclock->releaseMask == 0)
3374  continue;
3375 
3376  /* Else we should be releasing all locks */
3377  if (proclock->releaseMask != proclock->holdMask)
3378  elog(PANIC, "we seem to have dropped a bit somewhere");
3379 
3380  /*
3381  * We cannot simply modify proclock->tag.myProc to reassign
3382  * ownership of the lock, because that's part of the hash key and
3383  * the proclock would then be in the wrong hash chain. Instead
3384  * use hash_update_hash_key. (We used to create a new hash entry,
3385  * but that risks out-of-memory failure if other processes are
3386  * busy making proclocks too.) We must unlink the proclock from
3387  * our procLink chain and put it into the new proc's chain, too.
3388  *
3389  * Note: the updated proclock hash key will still belong to the
3390  * same hash partition, cf proclock_hash(). So the partition lock
3391  * we already hold is sufficient for this.
3392  */
3393  SHMQueueDelete(&proclock->procLink);
3394 
3395  /*
3396  * Create the new hash key for the proclock.
3397  */
3398  proclocktag.myLock = lock;
3399  proclocktag.myProc = newproc;
3400 
3401  /*
3402  * Update groupLeader pointer to point to the new proc. (We'd
3403  * better not be a member of somebody else's lock group!)
3404  */
3405  Assert(proclock->groupLeader == proclock->tag.myProc);
3406  proclock->groupLeader = newproc;
3407 
3408  /*
3409  * Update the proclock. We should not find any existing entry for
3410  * the same hash key, since there can be only one entry for any
3411  * given lock with my own proc.
3412  */
3414  (void *) proclock,
3415  (void *) &proclocktag))
3416  elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3417 
3418  /* Re-link into the new proc's proclock list */
3419  SHMQueueInsertBefore(&(newproc->myProcLocks[partition]),
3420  &proclock->procLink);
3421 
3422  PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3423  } /* loop over PROCLOCKs within this partition */
3424 
3425  LWLockRelease(partitionLock);
3426  } /* loop over partitions */
3427 
3428  END_CRIT_SECTION();
3429 }
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:134
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
int errcode(int sqlerrcode)
Definition: elog.c:570
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:1296
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:784
#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