PostgreSQL Source Code  git master
lock.h File Reference
#include "storage/backendid.h"
#include "storage/lockdefs.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_DATABASE_FROZEN_IDS(locktag, dboid)
 
#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 LOCK_LOCKTAG(lock)   ((LockTagType) (lock).tag.locktag_type)
 
#define PROCLOCK_LOCKMETHOD(proclock)   LOCK_LOCKMETHOD(*((proclock).tag.myLock))
 
#define LOCALLOCK_LOCKMETHOD(llock)   ((llock).tag.lock.locktag_lockmethodid)
 
#define LOCALLOCK_LOCKTAG(llock)   ((LockTagType) (llock).tag.lock.locktag_type)
 
#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_DATABASE_FROZEN_IDS, 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, int *countp)
 
void AtPrepare_Locks (void)
 
void PostPrepare_Locks (TransactionId xid)
 
bool 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 79 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 432 of file lock.h.

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

◆ LOCALLOCK_LOCKTAG

#define LOCALLOCK_LOCKTAG (   llock)    ((LockTagType) (llock).tag.lock.locktag_type)

Definition at line 433 of file lock.h.

Referenced by CheckAndSetLockHeld().

◆ LocalTransactionIdIsValid

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

Definition at line 69 of file lock.h.

Referenced by GetNextLocalTransactionId(), and VirtualXactLockTableCleanup().

◆ LOCK_LOCKMETHOD

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

Definition at line 313 of file lock.h.

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

◆ LOCK_LOCKTAG

#define LOCK_LOCKTAG (   lock)    ((LockTagType) (lock).tag.locktag_type)

Definition at line 314 of file lock.h.

Referenced by FindLockCycleRecurseMember(), and LockCheckConflicts().

◆ LOCKBIT_OFF

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

Definition at line 87 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 512 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 529 of file lock.h.

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

◆ LOCKTAG_LAST_TYPE

#define LOCKTAG_LAST_TYPE   LOCKTAG_ADVISORY

Definition at line 152 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 371 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:128

Definition at line 270 of file lock.h.

◆ SET_LOCKTAG_DATABASE_FROZEN_IDS

#define SET_LOCKTAG_DATABASE_FROZEN_IDS (   locktag,
  dboid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = 0, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_DATABASE_FROZEN_IDS, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127

Definition at line 199 of file lock.h.

Referenced by LockDatabaseFrozenIds().

◆ 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:127
Oid classoid
Definition: pg_shseclabel.h:31

Definition at line 262 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:127

Definition at line 208 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:127

Definition at line 181 of file lock.h.

Referenced by CheckRelationLockedByMe(), ConditionalLockRelation(), DefineIndex(), GetLockStatusData(), index_drop(), LockHasWaitersRelation(), LockRelation(), LockRelationIdForSession(), ReindexRelationConcurrently(), 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:127

Definition at line 190 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:127

Definition at line 247 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:127

Definition at line 226 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:127

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:127

Definition at line 235 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:68

Definition at line 76 of file lock.h.

Referenced by InitPredicateLocks(), and WaitForOlderSnapshots().

◆ USER_LOCKMETHOD

#define USER_LOCKMETHOD   2

Definition at line 128 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 73 of file lock.h.

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

◆ VirtualTransactionIdIsValid

#define VirtualTransactionIdIsValid (   vxid)

Typedef Documentation

◆ BlockedProcData

◆ BlockedProcsData

◆ LOCALLOCK

typedef struct LOCALLOCK LOCALLOCK

◆ LOCALLOCKOWNER

◆ LOCALLOCKTAG

typedef struct LOCALLOCKTAG LOCALLOCKTAG

◆ LOCK

typedef struct LOCK LOCK

◆ LockData

typedef struct LockData LockData

◆ LockInstanceData

◆ LockMethod

typedef const LockMethodData* LockMethod

Definition at line 118 of file lock.h.

◆ LockMethodData

◆ LOCKMETHODID

Definition at line 124 of file lock.h.

◆ LOCKTAG

typedef struct LOCKTAG LOCKTAG

◆ LockTagType

typedef enum LockTagType LockTagType

◆ PGPROC

typedef struct PGPROC PGPROC

Definition at line 27 of file lock.h.

◆ PROC_QUEUE

typedef struct PROC_QUEUE PROC_QUEUE

◆ PROCLOCK

typedef struct PROCLOCK PROCLOCK

◆ PROCLOCKTAG

typedef struct PROCLOCKTAG 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 496 of file lock.h.

497 {
498  DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
499  DS_NO_DEADLOCK, /* no deadlock detected */
500  DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
501  DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
502  DS_BLOCKED_BY_AUTOVACUUM /* no deadlock; queue blocked by autovacuum
503  * worker */
504 } DeadLockState;
DeadLockState
Definition: lock.h:496

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 
LOCKACQUIRE_ALREADY_CLEAR 

Definition at line 487 of file lock.h.

488 {
489  LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
490  LOCKACQUIRE_OK, /* lock successfully acquired */
491  LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
492  LOCKACQUIRE_ALREADY_CLEAR /* incremented count for lock already clear */
LockAcquireResult
Definition: lock.h:487

◆ LockTagType

Enumerator
LOCKTAG_RELATION 
LOCKTAG_RELATION_EXTEND 
LOCKTAG_DATABASE_FROZEN_IDS 
LOCKTAG_PAGE 
LOCKTAG_TUPLE 
LOCKTAG_TRANSACTION 
LOCKTAG_VIRTUALTRANSACTION 
LOCKTAG_SPECULATIVE_TOKEN 
LOCKTAG_OBJECT 
LOCKTAG_USERLOCK 
LOCKTAG_ADVISORY 

Definition at line 137 of file lock.h.

138 {
139  LOCKTAG_RELATION, /* whole relation */
140  LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */
141  LOCKTAG_DATABASE_FROZEN_IDS, /* pg_database.datfrozenxid */
142  LOCKTAG_PAGE, /* one page of a relation */
143  LOCKTAG_TUPLE, /* one physical tuple */
144  LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */
145  LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */
146  LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */
147  LOCKTAG_OBJECT, /* non-relation database object */
148  LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */
149  LOCKTAG_ADVISORY /* advisory user locks */
150 } LockTagType;
LockTagType
Definition: lock.h:137

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )

Definition at line 1757 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

1758 {
1759  uint32 fasthashcode;
1760  LOCALLOCK *locallock = StrongLockInProgress;
1761 
1762  if (locallock == NULL)
1763  return;
1764 
1765  fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1766  Assert(locallock->holdsStrongLockCount == true);
1768  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1769  FastPathStrongRelationLocks->count[fasthashcode]--;
1770  locallock->holdsStrongLockCount = false;
1771  StrongLockInProgress = NULL;
1773 }
uint32 hashcode
Definition: lock.h:421
bool holdsStrongLockCount
Definition: lock.h:428
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:268
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:262
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:286
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
unsigned int uint32
Definition: c.h:374
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

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

3231 {
3233  LOCALLOCK *locallock;
3234 
3235  /*
3236  * For the most part, we don't need to touch shared memory for this ---
3237  * all the necessary state information is in the locallock table.
3238  * Fast-path locks are an exception, however: we move any such locks to
3239  * the main table before allowing PREPARE TRANSACTION to succeed.
3240  */
3242 
3243  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3244  {
3245  TwoPhaseLockRecord record;
3246  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3247  bool haveSessionLock;
3248  bool haveXactLock;
3249  int i;
3250 
3251  /*
3252  * Ignore VXID locks. We don't want those to be held by prepared
3253  * transactions, since they aren't meaningful after a restart.
3254  */
3255  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3256  continue;
3257 
3258  /* Ignore it if we don't actually hold the lock */
3259  if (locallock->nLocks <= 0)
3260  continue;
3261 
3262  /* Scan to see whether we hold it at session or transaction level */
3263  haveSessionLock = haveXactLock = false;
3264  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3265  {
3266  if (lockOwners[i].owner == NULL)
3267  haveSessionLock = true;
3268  else
3269  haveXactLock = true;
3270  }
3271 
3272  /* Ignore it if we have only session lock */
3273  if (!haveXactLock)
3274  continue;
3275 
3276  /*
3277  * If we have both session- and transaction-level locks, fail. This
3278  * should never happen with regular locks, since we only take those at
3279  * session level in some special operations like VACUUM. It's
3280  * possible to hit this with advisory locks, though.
3281  *
3282  * It would be nice if we could keep the session hold and give away
3283  * the transactional hold to the prepared xact. However, that would
3284  * require two PROCLOCK objects, and we cannot be sure that another
3285  * PROCLOCK will be available when it comes time for PostPrepare_Locks
3286  * to do the deed. So for now, we error out while we can still do so
3287  * safely.
3288  */
3289  if (haveSessionLock)
3290  ereport(ERROR,
3291  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3292  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3293 
3294  /*
3295  * If the local lock was taken via the fast-path, we need to move it
3296  * to the primary lock table, or just get a pointer to the existing
3297  * primary lock table entry if by chance it's already been
3298  * transferred.
3299  */
3300  if (locallock->proclock == NULL)
3301  {
3302  locallock->proclock = FastPathGetRelationLockEntry(locallock);
3303  locallock->lock = locallock->proclock->tag.myLock;
3304  }
3305 
3306  /*
3307  * Arrange to not release any strong lock count held by this lock
3308  * entry. We must retain the count until the prepared transaction is
3309  * committed or rolled back.
3310  */
3311  locallock->holdsStrongLockCount = false;
3312 
3313  /*
3314  * Create a 2PC record.
3315  */
3316  memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3317  record.lockmode = locallock->tag.mode;
3318 
3320  &record, sizeof(TwoPhaseLockRecord));
3321  }
3322 }
PROCLOCKTAG tag
Definition: lock.h:361
LOCALLOCKTAG tag
Definition: lock.h:418
static HTAB * LockMethodLocalHash
Definition: lock.c:282
bool holdsStrongLockCount
Definition: lock.h:428
int numLockOwners
Definition: lock.h:425
LOCKTAG lock
Definition: lock.h:399
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition: lock.c:2810
LOCKMODE mode
Definition: lock.h:400
PROCLOCK * proclock
Definition: lock.h:423
Definition: lock.h:164
int errcode(int sqlerrcode)
Definition: elog.c:610
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1181
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
#define ereport(elevel,...)
Definition: elog.h:144
uint8 locktag_type
Definition: lock.h:170
#define TWOPHASE_RM_LOCK_ID
Definition: twophase_rmgr.h:25
LOCALLOCKOWNER * lockOwners
Definition: lock.h:427
LOCK * lock
Definition: lock.h:422
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
int64 nLocks
Definition: lock.h:424
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
LOCK * myLock
Definition: lock.h:354
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
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:31
SHM_QUEUE links
Definition: proc.h:115
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:306
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:1033
Definition: lock.h:297
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1628
#define Assert(condition)
Definition: c.h:745
static EDGE * possibleConstraints
Definition: deadlock.c:121
static bool DeadLockCheckRecurse(PGPROC *proc)
Definition: deadlock.c:315
#define elog(elevel,...)
Definition: elog.h:214
int i
int size
Definition: lock.h:32
static int nWaitOrders
Definition: deadlock.c:112
Definition: proc.h:112
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition: lock.c:487

◆ DeadLockReport()

void DeadLockReport ( void  )

Definition at line 1090 of file deadlock.c.

References _, appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), StringInfoData::data, DescribeLockTag(), ereport, errcode(), errdetail_internal(), errdetail_log(), errhint(), errmsg(), ERROR, GetLockmodeName(), i, initStringInfo(), StringInfoData::len, 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().

1091 {
1092  StringInfoData clientbuf; /* errdetail for client */
1093  StringInfoData logbuf; /* errdetail for server log */
1094  StringInfoData locktagbuf;
1095  int i;
1096 
1097  initStringInfo(&clientbuf);
1098  initStringInfo(&logbuf);
1099  initStringInfo(&locktagbuf);
1100 
1101  /* Generate the "waits for" lines sent to the client */
1102  for (i = 0; i < nDeadlockDetails; i++)
1103  {
1104  DEADLOCK_INFO *info = &deadlockDetails[i];
1105  int nextpid;
1106 
1107  /* The last proc waits for the first one... */
1108  if (i < nDeadlockDetails - 1)
1109  nextpid = info[1].pid;
1110  else
1111  nextpid = deadlockDetails[0].pid;
1112 
1113  /* reset locktagbuf to hold next object description */
1114  resetStringInfo(&locktagbuf);
1115 
1116  DescribeLockTag(&locktagbuf, &info->locktag);
1117 
1118  if (i > 0)
1119  appendStringInfoChar(&clientbuf, '\n');
1120 
1121  appendStringInfo(&clientbuf,
1122  _("Process %d waits for %s on %s; blocked by process %d."),
1123  info->pid,
1125  info->lockmode),
1126  locktagbuf.data,
1127  nextpid);
1128  }
1129 
1130  /* Duplicate all the above for the server ... */
1131  appendBinaryStringInfo(&logbuf, clientbuf.data, clientbuf.len);
1132 
1133  /* ... and add info about query strings */
1134  for (i = 0; i < nDeadlockDetails; i++)
1135  {
1136  DEADLOCK_INFO *info = &deadlockDetails[i];
1137 
1138  appendStringInfoChar(&logbuf, '\n');
1139 
1140  appendStringInfo(&logbuf,
1141  _("Process %d: %s"),
1142  info->pid,
1144  }
1145 
1147 
1148  ereport(ERROR,
1149  (errcode(ERRCODE_T_R_DEADLOCK_DETECTED),
1150  errmsg("deadlock detected"),
1151  errdetail_internal("%s", clientbuf.data),
1152  errdetail_log("%s", logbuf.data),
1153  errhint("See server log for query details.")));
1154 }
void pgstat_report_deadlock(void)
Definition: pgstat.c:1564
int errhint(const char *fmt,...)
Definition: elog.c:1071
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:4015
LOCKMODE lockmode
Definition: deadlock.c:74
int errcode(int sqlerrcode)
Definition: elog.c:610
int errdetail_internal(const char *fmt,...)
Definition: elog.c:984
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:43
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1100
static int nDeadlockDetails
Definition: deadlock.c:125
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:75
int errdetail_log(const char *fmt,...)
Definition: elog.c:1005
const char * pgstat_get_backend_current_activity(int pid, bool checkUser)
Definition: pgstat.c:4184
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define ereport(elevel,...)
Definition: elog.h:144
static DEADLOCK_INFO * deadlockDetails
Definition: deadlock.c:124
uint8 locktag_lockmethodid
Definition: lock.h:171
int errmsg(const char *fmt,...)
Definition: elog.c:824
int i
LOCKTAG locktag
Definition: deadlock.c:73
#define _(x)
Definition: elog.c:88
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 583 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

584 {
585  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
586 
587  if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
588  return true;
589 
590  return false;
591 }
const LOCKMASK * conflictTab
Definition: lock.h:113
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

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

3754 {
3755  BlockedProcsData *data;
3756  PGPROC *proc;
3757  int i;
3758 
3759  data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
3760 
3761  /*
3762  * Guess how much space we'll need, and preallocate. Most of the time
3763  * this will avoid needing to do repalloc while holding the LWLocks. (We
3764  * assume, but check with an Assert, that MaxBackends is enough entries
3765  * for the procs[] array; the other two could need enlargement, though.)
3766  */
3767  data->nprocs = data->nlocks = data->npids = 0;
3768  data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3769  data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
3770  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3771  data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3772 
3773  /*
3774  * In order to search the ProcArray for blocked_pid and assume that that
3775  * entry won't immediately disappear under us, we must hold ProcArrayLock.
3776  * In addition, to examine the lock grouping fields of any other backend,
3777  * we must hold all the hash partition locks. (Only one of those locks is
3778  * actually relevant for any one lock group, but we can't know which one
3779  * ahead of time.) It's fairly annoying to hold all those locks
3780  * throughout this, but it's no worse than GetLockStatusData(), and it
3781  * does have the advantage that we're guaranteed to return a
3782  * self-consistent instantaneous state.
3783  */
3784  LWLockAcquire(ProcArrayLock, LW_SHARED);
3785 
3786  proc = BackendPidGetProcWithLock(blocked_pid);
3787 
3788  /* Nothing to do if it's gone */
3789  if (proc != NULL)
3790  {
3791  /*
3792  * Acquire lock on the entire shared lock data structure. See notes
3793  * in GetLockStatusData().
3794  */
3795  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3797 
3798  if (proc->lockGroupLeader == NULL)
3799  {
3800  /* Easy case, proc is not a lock group member */
3801  GetSingleProcBlockerStatusData(proc, data);
3802  }
3803  else
3804  {
3805  /* Examine all procs in proc's lock group */
3806  dlist_iter iter;
3807 
3809  {
3810  PGPROC *memberProc;
3811 
3812  memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
3813  GetSingleProcBlockerStatusData(memberProc, data);
3814  }
3815  }
3816 
3817  /*
3818  * And release locks. See notes in GetLockStatusData().
3819  */
3820  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3822 
3823  Assert(data->nprocs <= data->maxprocs);
3824  }
3825 
3826  LWLockRelease(ProcArrayLock);
3827 
3828  return data;
3829 }
int * waiter_pids
Definition: lock.h:476
dlist_head lockGroupMembers
Definition: proc.h:240
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
BlockedProcData * procs
Definition: lock.h:474
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3003
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition: lock.c:3833
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:517
int MaxBackends
Definition: globals.c:136
int maxlocks
Definition: lock.h:480
LockInstanceData * locks
Definition: lock.h:475
dlist_node * cur
Definition: ilist.h:161
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * palloc(Size size)
Definition: mcxt.c:950
int i
Definition: proc.h:112
PGPROC * lockGroupLeader
Definition: proc.h:239
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:115
int maxprocs
Definition: lock.h:478

◆ 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:112

◆ GetLockConflicts()

VirtualTransactionId* GetLockConflicts ( const LOCKTAG locktag,
LOCKMODE  lockmode,
int *  countp 
)

Definition at line 2912 of file lock.c.

References PROC_HDR::allProcCount, PROC_HDR::allProcs, VirtualTransactionId::backendId, ConflictsWithRelationFastPath, LockMethodData::conflictTab, PGPROC::databaseId, elog, ERROR, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpInfoLock, 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().

2913 {
2914  static VirtualTransactionId *vxids;
2915  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
2916  LockMethod lockMethodTable;
2917  LOCK *lock;
2918  LOCKMASK conflictMask;
2919  SHM_QUEUE *procLocks;
2920  PROCLOCK *proclock;
2921  uint32 hashcode;
2922  LWLock *partitionLock;
2923  int count = 0;
2924  int fast_count = 0;
2925 
2926  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2927  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2928  lockMethodTable = LockMethods[lockmethodid];
2929  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2930  elog(ERROR, "unrecognized lock mode: %d", lockmode);
2931 
2932  /*
2933  * Allocate memory to store results, and fill with InvalidVXID. We only
2934  * need enough space for MaxBackends + a terminator, since prepared xacts
2935  * don't count. InHotStandby allocate once in TopMemoryContext.
2936  */
2937  if (InHotStandby)
2938  {
2939  if (vxids == NULL)
2940  vxids = (VirtualTransactionId *)
2942  sizeof(VirtualTransactionId) * (MaxBackends + 1));
2943  }
2944  else
2945  vxids = (VirtualTransactionId *)
2946  palloc0(sizeof(VirtualTransactionId) * (MaxBackends + 1));
2947 
2948  /* Compute hash code and partition lock, and look up conflicting modes. */
2949  hashcode = LockTagHashCode(locktag);
2950  partitionLock = LockHashPartitionLock(hashcode);
2951  conflictMask = lockMethodTable->conflictTab[lockmode];
2952 
2953  /*
2954  * Fast path locks might not have been entered in the primary lock table.
2955  * If the lock we're dealing with could conflict with such a lock, we must
2956  * examine each backend's fast-path array for conflicts.
2957  */
2958  if (ConflictsWithRelationFastPath(locktag, lockmode))
2959  {
2960  int i;
2961  Oid relid = locktag->locktag_field2;
2962  VirtualTransactionId vxid;
2963 
2964  /*
2965  * Iterate over relevant PGPROCs. Anything held by a prepared
2966  * transaction will have been transferred to the primary lock table,
2967  * so we need not worry about those. This is all a bit fuzzy, because
2968  * new locks could be taken after we've visited a particular
2969  * partition, but the callers had better be prepared to deal with that
2970  * anyway, since the locks could equally well be taken between the
2971  * time we return the value and the time the caller does something
2972  * with it.
2973  */
2974  for (i = 0; i < ProcGlobal->allProcCount; i++)
2975  {
2976  PGPROC *proc = &ProcGlobal->allProcs[i];
2977  uint32 f;
2978 
2979  /* A backend never blocks itself */
2980  if (proc == MyProc)
2981  continue;
2982 
2984 
2985  /*
2986  * If the target backend isn't referencing the same database as
2987  * the lock, then we needn't examine the individual relation IDs
2988  * at all; none of them can be relevant.
2989  *
2990  * See FastPathTransferRelationLocks() for discussion of why we do
2991  * this test after acquiring the lock.
2992  */
2993  if (proc->databaseId != locktag->locktag_field1)
2994  {
2995  LWLockRelease(&proc->fpInfoLock);
2996  continue;
2997  }
2998 
2999  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
3000  {
3001  uint32 lockmask;
3002 
3003  /* Look for an allocated slot matching the given relid. */
3004  if (relid != proc->fpRelId[f])
3005  continue;
3006  lockmask = FAST_PATH_GET_BITS(proc, f);
3007  if (!lockmask)
3008  continue;
3009  lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
3010 
3011  /*
3012  * There can only be one entry per relation, so if we found it
3013  * and it doesn't conflict, we can skip the rest of the slots.
3014  */
3015  if ((lockmask & conflictMask) == 0)
3016  break;
3017 
3018  /* Conflict! */
3019  GET_VXID_FROM_PGPROC(vxid, *proc);
3020 
3021  /*
3022  * If we see an invalid VXID, then either the xact has already
3023  * committed (or aborted), or it's a prepared xact. In either
3024  * case we may ignore it.
3025  */
3026  if (VirtualTransactionIdIsValid(vxid))
3027  vxids[count++] = vxid;
3028 
3029  /* No need to examine remaining slots. */
3030  break;
3031  }
3032 
3033  LWLockRelease(&proc->fpInfoLock);
3034  }
3035  }
3036 
3037  /* Remember how many fast-path conflicts we found. */
3038  fast_count = count;
3039 
3040  /*
3041  * Look up the lock object matching the tag.
3042  */
3043  LWLockAcquire(partitionLock, LW_SHARED);
3044 
3046  (const void *) locktag,
3047  hashcode,
3048  HASH_FIND,
3049  NULL);
3050  if (!lock)
3051  {
3052  /*
3053  * If the lock object doesn't exist, there is nothing holding a lock
3054  * on this lockable object.
3055  */
3056  LWLockRelease(partitionLock);
3057  vxids[count].backendId = InvalidBackendId;
3059  if (countp)
3060  *countp = count;
3061  return vxids;
3062  }
3063 
3064  /*
3065  * Examine each existing holder (or awaiter) of the lock.
3066  */
3067 
3068  procLocks = &(lock->procLocks);
3069 
3070  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3071  offsetof(PROCLOCK, lockLink));
3072 
3073  while (proclock)
3074  {
3075  if (conflictMask & proclock->holdMask)
3076  {
3077  PGPROC *proc = proclock->tag.myProc;
3078 
3079  /* A backend never blocks itself */
3080  if (proc != MyProc)
3081  {
3082  VirtualTransactionId vxid;
3083 
3084  GET_VXID_FROM_PGPROC(vxid, *proc);
3085 
3086  /*
3087  * If we see an invalid VXID, then either the xact has already
3088  * committed (or aborted), or it's a prepared xact. In either
3089  * case we may ignore it.
3090  */
3091  if (VirtualTransactionIdIsValid(vxid))
3092  {
3093  int i;
3094 
3095  /* Avoid duplicate entries. */
3096  for (i = 0; i < fast_count; ++i)
3097  if (VirtualTransactionIdEquals(vxids[i], vxid))
3098  break;
3099  if (i >= fast_count)
3100  vxids[count++] = vxid;
3101  }
3102  }
3103  }
3104 
3105  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3106  offsetof(PROCLOCK, lockLink));
3107  }
3108 
3109  LWLockRelease(partitionLock);
3110 
3111  if (count > MaxBackends) /* should never happen */
3112  elog(PANIC, "too many conflicting locks found");
3113 
3114  vxids[count].backendId = InvalidBackendId;
3116  if (countp)
3117  *countp = count;
3118  return vxids;
3119 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:932
PROCLOCKTAG tag
Definition: lock.h:361
Definition: lwlock.h:31
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:232
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:365
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
const LOCKMASK * conflictTab
Definition: lock.h:113
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
SHM_QUEUE lockLink
Definition: lock.h:367
#define InHotStandby
Definition: xlog.h:74
PROC_HDR * ProcGlobal
Definition: proc.c:79
#define lengthof(array)
Definition: c.h:675
unsigned int Oid
Definition: postgres_ext.h:31
LocalTransactionId localTransactionId
Definition: lock.h:65
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
#define ERROR
Definition: elog.h:43
int MaxBackends
Definition: globals.c:136
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
uint32 locktag_field2
Definition: lock.h:167
Oid databaseId
Definition: proc.h:145
unsigned int uint32
Definition: c.h:374
Definition: lock.h:297
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:517
MemoryContext TopMemoryContext
Definition: mcxt.c:44
uint16 LOCKMETHODID
Definition: lock.h:124
SHM_QUEUE procLocks
Definition: lock.h:305
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:981
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:230
BackendId backendId
Definition: lock.h:64
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint32 allProcCount
Definition: proc.h:324
int LOCKMASK
Definition: lockdefs.h:25
uint8 locktag_lockmethodid
Definition: lock.h:171
PGPROC * myProc
Definition: lock.h:355
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:202
Definition: lock.h:358
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define elog(elevel,...)
Definition: elog.h:214
#define InvalidLocalTransactionId
Definition: lock.h:68
int i
PGPROC * allProcs
Definition: proc.h:306
static const LockMethod LockMethods[]
Definition: lock.c:150
LWLock fpInfoLock
Definition: proc.h:228
uint32 locktag_field1
Definition: lock.h:166
Definition: proc.h:112
#define offsetof(type, field)
Definition: c.h:668
int numLockModes
Definition: lock.h:112

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

Definition at line 4015 of file lock.c.

References Assert, elog, hash_seq_init(), hash_seq_search(), i, lengthof, LOCK_PRINT, LockMethodData::lockModeNames, LOG, mode, 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().

4016 {
4017  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
4018  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
4019  return LockMethods[lockmethodid]->lockModeNames[mode];
4020 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define lengthof(array)
Definition: c.h:675
#define Assert(condition)
Definition: c.h:745
static const LockMethod LockMethods[]
Definition: lock.c:150
const char *const * lockModeNames
Definition: lock.h:114

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)

Definition at line 487 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

488 {
489  LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
490 
491  Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
492  return LockMethods[lockmethodid];
493 }
#define lengthof(array)
Definition: c.h:675
uint16 LOCKMETHODID
Definition: lock.h:124
#define Assert(condition)
Definition: c.h:745
static const LockMethod LockMethods[]
Definition: lock.c:150
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:313

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

Definition at line 3569 of file lock.c.

References PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert, LockInstanceData::backend, VirtualTransactionId::backendId, PGPROC::backendId, PGPROC::databaseId, ExclusiveLock, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, LockInstanceData::fastpath, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpInfoLock, 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().

3570 {
3571  LockData *data;
3572  PROCLOCK *proclock;
3573  HASH_SEQ_STATUS seqstat;
3574  int els;
3575  int el;
3576  int i;
3577 
3578  data = (LockData *) palloc(sizeof(LockData));
3579 
3580  /* Guess how much space we'll need. */
3581  els = MaxBackends;
3582  el = 0;
3583  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3584 
3585  /*
3586  * First, we iterate through the per-backend fast-path arrays, locking
3587  * them one at a time. This might produce an inconsistent picture of the
3588  * system state, but taking all of those LWLocks at the same time seems
3589  * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3590  * matter too much, because none of these locks can be involved in lock
3591  * conflicts anyway - anything that might must be present in the main lock
3592  * table. (For the same reason, we don't sweat about making leaderPid
3593  * completely valid. We cannot safely dereference another backend's
3594  * lockGroupLeader field without holding all lock partition locks, and
3595  * it's not worth that.)
3596  */
3597  for (i = 0; i < ProcGlobal->allProcCount; ++i)
3598  {
3599  PGPROC *proc = &ProcGlobal->allProcs[i];
3600  uint32 f;
3601 
3603 
3604  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
3605  {
3606  LockInstanceData *instance;
3607  uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3608 
3609  /* Skip unallocated slots. */
3610  if (!lockbits)
3611  continue;
3612 
3613  if (el >= els)
3614  {
3615  els += MaxBackends;
3616  data->locks = (LockInstanceData *)
3617  repalloc(data->locks, sizeof(LockInstanceData) * els);
3618  }
3619 
3620  instance = &data->locks[el];
3621  SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3622  proc->fpRelId[f]);
3623  instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3624  instance->waitLockMode = NoLock;
3625  instance->backend = proc->backendId;
3626  instance->lxid = proc->lxid;
3627  instance->pid = proc->pid;
3628  instance->leaderPid = proc->pid;
3629  instance->fastpath = true;
3630 
3631  el++;
3632  }
3633 
3634  if (proc->fpVXIDLock)
3635  {
3636  VirtualTransactionId vxid;
3637  LockInstanceData *instance;
3638 
3639  if (el >= els)
3640  {
3641  els += MaxBackends;
3642  data->locks = (LockInstanceData *)
3643  repalloc(data->locks, sizeof(LockInstanceData) * els);
3644  }
3645 
3646  vxid.backendId = proc->backendId;
3648 
3649  instance = &data->locks[el];
3650  SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3651  instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3652  instance->waitLockMode = NoLock;
3653  instance->backend = proc->backendId;
3654  instance->lxid = proc->lxid;
3655  instance->pid = proc->pid;
3656  instance->leaderPid = proc->pid;
3657  instance->fastpath = true;
3658 
3659  el++;
3660  }
3661 
3662  LWLockRelease(&proc->fpInfoLock);
3663  }
3664 
3665  /*
3666  * Next, acquire lock on the entire shared lock data structure. We do
3667  * this so that, at least for locks in the primary lock table, the state
3668  * will be self-consistent.
3669  *
3670  * Since this is a read-only operation, we take shared instead of
3671  * exclusive lock. There's not a whole lot of point to this, because all
3672  * the normal operations require exclusive lock, but it doesn't hurt
3673  * anything either. It will at least allow two backends to do
3674  * GetLockStatusData in parallel.
3675  *
3676  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3677  */
3678  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3680 
3681  /* Now we can safely count the number of proclocks */
3683  if (data->nelements > els)
3684  {
3685  els = data->nelements;
3686  data->locks = (LockInstanceData *)
3687  repalloc(data->locks, sizeof(LockInstanceData) * els);
3688  }
3689 
3690  /* Now scan the tables to copy the data */
3692 
3693  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3694  {
3695  PGPROC *proc = proclock->tag.myProc;
3696  LOCK *lock = proclock->tag.myLock;
3697  LockInstanceData *instance = &data->locks[el];
3698 
3699  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3700  instance->holdMask = proclock->holdMask;
3701  if (proc->waitLock == proclock->tag.myLock)
3702  instance->waitLockMode = proc->waitLockMode;
3703  else
3704  instance->waitLockMode = NoLock;
3705  instance->backend = proc->backendId;
3706  instance->lxid = proc->lxid;
3707  instance->pid = proc->pid;
3708  instance->leaderPid = proclock->groupLeader->pid;
3709  instance->fastpath = false;
3710 
3711  el++;
3712  }
3713 
3714  /*
3715  * And release locks. We do this in reverse order for two reasons: (1)
3716  * Anyone else who needs more than one of the locks will be trying to lock
3717  * them in increasing order; we don't want to release the other process
3718  * until it can get all the locks it needs. (2) This avoids O(N^2)
3719  * behavior inside LWLockRelease.
3720  */
3721  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3723 
3724  Assert(el == data->nelements);
3725 
3726  return data;
3727 }
PROCLOCKTAG tag
Definition: lock.h:361
LockInstanceData * locks
Definition: lock.h:456
BackendId backendId
Definition: proc.h:144
#define ExclusiveLock
Definition: lockdefs.h:44
LOCKMASK holdMask
Definition: lock.h:365
bool fastpath
Definition: lock.h:450
LOCKMODE waitLockMode
Definition: proc.h:172
LOCKTAG tag
Definition: lock.h:300
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
Definition: lock.h:164
PROC_HDR * ProcGlobal
Definition: proc.c:79
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1347
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
bool fpVXIDLock
Definition: proc.h:231
Definition: lock.h:453
LocalTransactionId localTransactionId
Definition: lock.h:65
LOCKTAG locktag
Definition: lock.h:443
LOCKMODE waitLockMode
Definition: lock.h:445
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int leaderPid
Definition: lock.h:449
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:517
int MaxBackends
Definition: globals.c:136
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:181
#define NoLock
Definition: lockdefs.h:34
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
Oid databaseId
Definition: proc.h:145
unsigned int uint32
Definition: c.h:374
Definition: lock.h:297
LOCK * waitLock
Definition: proc.h:170
int nelements
Definition: lock.h:455
BackendId backend
Definition: lock.h:446
LocalTransactionId lxid
Definition: lock.h:447
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:230
#define Assert(condition)
Definition: c.h:745
BackendId backendId
Definition: lock.h:64
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition: lock.h:235
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
uint32 allProcCount
Definition: proc.h:324
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
LOCKMASK holdMask
Definition: lock.h:444
PGPROC * myProc
Definition: lock.h:355
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:202
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:358
void * palloc(Size size)
Definition: mcxt.c:950
int i
LOCK * myLock
Definition: lock.h:354
PGPROC * allProcs
Definition: proc.h:306
LWLock fpInfoLock
Definition: proc.h:228
Definition: proc.h:112
int pid
Definition: proc.h:137
LocalTransactionId fpLocalTransactionId
Definition: proc.h:232
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:115
PGPROC * groupLeader
Definition: lock.h:364
LocalTransactionId lxid
Definition: proc.h:134

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 499 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

500 {
501  LOCKMETHODID lockmethodid = (LOCKMETHODID) locktag->locktag_lockmethodid;
502 
503  Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
504  return LockMethods[lockmethodid];
505 }
#define lengthof(array)
Definition: c.h:675
uint16 LOCKMETHODID
Definition: lock.h:124
#define Assert(condition)
Definition: c.h:745
uint8 locktag_lockmethodid
Definition: lock.h:171
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

Definition at line 3933 of file lock.c.

References AccessExclusiveLock, 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(), xl_standby_lock::relOid, LOCK::tag, PROCLOCK::tag, TransactionIdIsValid, xl_standby_lock::xid, and PGPROC::xid.

Referenced by LogStandbySnapshot().

3934 {
3935  xl_standby_lock *accessExclusiveLocks;
3936  PROCLOCK *proclock;
3937  HASH_SEQ_STATUS seqstat;
3938  int i;
3939  int index;
3940  int els;
3941 
3942  /*
3943  * Acquire lock on the entire shared lock data structure.
3944  *
3945  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3946  */
3947  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3949 
3950  /* Now we can safely count the number of proclocks */
3952 
3953  /*
3954  * Allocating enough space for all locks in the lock table is overkill,
3955  * but it's more convenient and faster than having to enlarge the array.
3956  */
3957  accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
3958 
3959  /* Now scan the tables to copy the data */
3961 
3962  /*
3963  * If lock is a currently granted AccessExclusiveLock then it will have
3964  * just one proclock holder, so locks are never accessed twice in this
3965  * particular case. Don't copy this code for use elsewhere because in the
3966  * general case this will give you duplicate locks when looking at
3967  * non-exclusive lock types.
3968  */
3969  index = 0;
3970  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3971  {
3972  /* make sure this definition matches the one used in LockAcquire */
3973  if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
3974  proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION)
3975  {
3976  PGPROC *proc = proclock->tag.myProc;
3977  LOCK *lock = proclock->tag.myLock;
3978  TransactionId xid = proc->xid;
3979 
3980  /*
3981  * Don't record locks for transactions if we know they have
3982  * already issued their WAL record for commit but not yet released
3983  * lock. It is still possible that we see locks held by already
3984  * complete transactions, if they haven't yet zeroed their xids.
3985  */
3986  if (!TransactionIdIsValid(xid))
3987  continue;
3988 
3989  accessExclusiveLocks[index].xid = xid;
3990  accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
3991  accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
3992 
3993  index++;
3994  }
3995  }
3996 
3997  Assert(index <= els);
3998 
3999  /*
4000  * And release locks. We do this in reverse order for two reasons: (1)
4001  * Anyone else who needs more than one of the locks will be trying to lock
4002  * them in increasing order; we don't want to release the other process
4003  * until it can get all the locks it needs. (2) This avoids O(N^2)
4004  * behavior inside LWLockRelease.
4005  */
4006  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
4008 
4009  *nlocks = index;
4010  return accessExclusiveLocks;
4011 }
PROCLOCKTAG tag
Definition: lock.h:361
uint32 TransactionId
Definition: c.h:520
LOCKMASK holdMask
Definition: lock.h:365
LOCKTAG tag
Definition: lock.h:300
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1347
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:517
uint32 locktag_field2
Definition: lock.h:167
Definition: lock.h:297
TransactionId xid
Definition: lockdefs.h:54
uint8 locktag_type
Definition: lock.h:170
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
PGPROC * myProc
Definition: lock.h:355
TransactionId xid
Definition: proc.h:124
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: lock.h:358
void * palloc(Size size)
Definition: mcxt.c:950
int i
LOCK * myLock
Definition: lock.h:354
#define TransactionIdIsValid(xid)
Definition: transam.h:41
uint32 locktag_field1
Definition: lock.h:166
Definition: proc.h:112
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:115

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1786 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

1787 {
1789 }
static LOCALLOCK * awaitedLock
Definition: lock.c:287
static ResourceOwner awaitedOwner
Definition: lock.c:288
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1689

◆ GrantLock()

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

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

1556 {
1557  lock->nGranted++;
1558  lock->granted[lockmode]++;
1559  lock->grantMask |= LOCKBIT_ON(lockmode);
1560  if (lock->granted[lockmode] == lock->requested[lockmode])
1561  lock->waitMask &= LOCKBIT_OFF(lockmode);
1562  proclock->holdMask |= LOCKBIT_ON(lockmode);
1563  LOCK_PRINT("GrantLock", lock, lockmode);
1564  Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1565  Assert(lock->nGranted <= lock->nRequested);
1566 }
int nRequested
Definition: lock.h:308
LOCKMASK holdMask
Definition: lock.h:365
int nGranted
Definition: lock.h:310
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:87
int granted[MAX_LOCKMODES]
Definition: lock.h:309
LOCKMASK waitMask
Definition: lock.h:304
int requested[MAX_LOCKMODES]
Definition: lock.h:307
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define Assert(condition)
Definition: c.h:745
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:303

◆ 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:136
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:950
static int maxPossibleConstraints
Definition: deadlock.c:123
static int * beforeConstraints
Definition: deadlock.c:107
Definition: proc.h:112

◆ InitLocks()

void InitLocks ( void  )

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

405 {
406  HASHCTL info;
407  long init_table_size,
408  max_table_size;
409  bool found;
410 
411  /*
412  * Compute init/max size to request for lock hashtables. Note these
413  * calculations must agree with LockShmemSize!
414  */
415  max_table_size = NLOCKENTS();
416  init_table_size = max_table_size / 2;
417 
418  /*
419  * Allocate hash table for LOCK structs. This stores per-locked-object
420  * information.
421  */
422  MemSet(&info, 0, sizeof(info));
423  info.keysize = sizeof(LOCKTAG);
424  info.entrysize = sizeof(LOCK);
426 
427  LockMethodLockHash = ShmemInitHash("LOCK hash",
428  init_table_size,
429  max_table_size,
430  &info,
432 
433  /* Assume an average of 2 holders per lock */
434  max_table_size *= 2;
435  init_table_size *= 2;
436 
437  /*
438  * Allocate hash table for PROCLOCK structs. This stores
439  * per-lock-per-holder information.
440  */
441  info.keysize = sizeof(PROCLOCKTAG);
442  info.entrysize = sizeof(PROCLOCK);
443  info.hash = proclock_hash;
445 
446  LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
447  init_table_size,
448  max_table_size,
449  &info,
451 
452  /*
453  * Allocate fast-path structures.
454  */
456  ShmemInitStruct("Fast Path Strong Relation Lock Data",
457  sizeof(FastPathStrongRelationLockData), &found);
458  if (!found)
460 
461  /*
462  * Allocate non-shared hash table for LOCALLOCK structs. This stores lock
463  * counts and resource owner information.
464  *
465  * The non-shared table could already exist in this process (this occurs
466  * when the postmaster is recreating shared memory after a backend crash).
467  * If so, delete and recreate it. (We could simply leave it, since it
468  * ought to be empty in the postmaster, but for safety let's zap it.)
469  */
472 
473  info.keysize = sizeof(LOCALLOCKTAG);
474  info.entrysize = sizeof(LOCALLOCK);
475 
476  LockMethodLocalHash = hash_create("LOCALLOCK hash",
477  16,
478  &info,
480 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:827
static HTAB * LockMethodLocalHash
Definition: lock.c:282
#define HASH_ELEM
Definition: hsearch.h:85
#define SpinLockInit(lock)
Definition: spin.h:60
Size entrysize
Definition: hsearch.h:72
static uint32 proclock_hash(const void *key, Size keysize)
Definition: lock.c:534
#define MemSet(start, val, len)
Definition: c.h:949
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
struct LOCALLOCKTAG LOCALLOCKTAG
#define HASH_PARTITION
Definition: hsearch.h:82
#define NLOCKENTS()
Definition: lock.c:56
struct LOCALLOCK LOCALLOCK
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
long num_partitions
Definition: hsearch.h:67
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:392
struct PROCLOCK PROCLOCK
struct LOCKTAG LOCKTAG
#define HASH_BLOBS
Definition: hsearch.h:86
struct PROCLOCKTAG PROCLOCKTAG
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:326
Size keysize
Definition: hsearch.h:71
struct LOCK LOCK
static HTAB * LockMethodLockHash
Definition: lock.c:280
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:337
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:115
HashValueFunc hash
Definition: hsearch.h:73
#define HASH_FUNCTION
Definition: hsearch.h:87

◆ lock_twophase_postabort()

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

Definition at line 4367 of file lock.c.

References lock_twophase_postcommit().

4369 {
4370  lock_twophase_postcommit(xid, info, recdata, len);
4371 }
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
Definition: lock.c:4341

◆ lock_twophase_postcommit()

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

Definition at line 4341 of file lock.c.

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

Referenced by lock_twophase_postabort().

4343 {
4344  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4345  PGPROC *proc = TwoPhaseGetDummyProc(xid, true);
4346  LOCKTAG *locktag;
4347  LOCKMETHODID lockmethodid;
4348  LockMethod lockMethodTable;
4349 
4350  Assert(len == sizeof(TwoPhaseLockRecord));
4351  locktag = &rec->locktag;
4352  lockmethodid = locktag->locktag_lockmethodid;
4353 
4354  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4355  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4356  lockMethodTable = LockMethods[lockmethodid];
4357 
4358  LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4359 }
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3133
Definition: lock.h:164
#define lengthof(array)
Definition: c.h:675
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:873
uint16 LOCKMETHODID
Definition: lock.h:124
#define Assert(condition)
Definition: c.h:745
uint8 locktag_lockmethodid
Definition: lock.h:171
#define elog(elevel,...)
Definition: elog.h:214
static const LockMethod LockMethods[]
Definition: lock.c:150
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:112

◆ lock_twophase_recover()

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

Definition at line 4128 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.

4130 {
4131  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4132  PGPROC *proc = TwoPhaseGetDummyProc(xid, false);
4133  LOCKTAG *locktag;
4134  LOCKMODE lockmode;
4135  LOCKMETHODID lockmethodid;
4136  LOCK *lock;
4137  PROCLOCK *proclock;
4138  PROCLOCKTAG proclocktag;
4139  bool found;
4140  uint32 hashcode;
4141  uint32 proclock_hashcode;
4142  int partition;
4143  LWLock *partitionLock;
4144  LockMethod lockMethodTable;
4145 
4146  Assert(len == sizeof(TwoPhaseLockRecord));
4147  locktag = &rec->locktag;
4148  lockmode = rec->lockmode;
4149  lockmethodid = locktag->locktag_lockmethodid;
4150 
4151  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4152  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4153  lockMethodTable = LockMethods[lockmethodid];
4154 
4155  hashcode = LockTagHashCode(locktag);
4156  partition = LockHashPartition(hashcode);
4157  partitionLock = LockHashPartitionLock(hashcode);
4158 
4159  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4160 
4161  /*
4162  * Find or create a lock with this tag.
4163  */
4165  (void *) locktag,
4166  hashcode,
4168  &found);
4169  if (!lock)
4170  {
4171  LWLockRelease(partitionLock);
4172  ereport(ERROR,
4173  (errcode(ERRCODE_OUT_OF_MEMORY),
4174  errmsg("out of shared memory"),
4175  errhint("You might need to increase max_locks_per_transaction.")));
4176  }
4177 
4178  /*
4179  * if it's a new lock object, initialize it
4180  */
4181  if (!found)
4182  {
4183  lock->grantMask = 0;
4184  lock->waitMask = 0;
4185  SHMQueueInit(&(lock->procLocks));
4186  ProcQueueInit(&(lock->waitProcs));
4187  lock->nRequested = 0;
4188  lock->nGranted = 0;
4189  MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4190  MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4191  LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4192  }
4193  else
4194  {
4195  LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4196  Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4197  Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4198  Assert(lock->nGranted <= lock->nRequested);
4199  }
4200 
4201  /*
4202  * Create the hash key for the proclock table.
4203  */
4204  proclocktag.myLock = lock;
4205  proclocktag.myProc = proc;
4206 
4207  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4208 
4209  /*
4210  * Find or create a proclock entry with this tag
4211  */
4213  (void *) &proclocktag,
4214  proclock_hashcode,
4216  &found);
4217  if (!proclock)
4218  {
4219  /* Oops, not enough shmem for the proclock */
4220  if (lock->nRequested == 0)
4221  {
4222  /*
4223  * There are no other requestors of this lock, so garbage-collect
4224  * the lock object. We *must* do this to avoid a permanent leak
4225  * of shared memory, because there won't be anything to cause
4226  * anyone to release the lock object later.
4227  */
4228  Assert(SHMQueueEmpty(&(lock->procLocks)));
4230  (void *) &(lock->tag),
4231  hashcode,
4232  HASH_REMOVE,
4233  NULL))
4234  elog(PANIC, "lock table corrupted");
4235  }
4236  LWLockRelease(partitionLock);
4237  ereport(ERROR,
4238  (errcode(ERRCODE_OUT_OF_MEMORY),
4239  errmsg("out of shared memory"),
4240  errhint("You might need to increase max_locks_per_transaction.")));
4241  }
4242 
4243  /*
4244  * If new, initialize the new entry
4245  */
4246  if (!found)
4247  {
4248  Assert(proc->lockGroupLeader == NULL);
4249  proclock->groupLeader = proc;
4250  proclock->holdMask = 0;
4251  proclock->releaseMask = 0;
4252  /* Add proclock to appropriate lists */
4253  SHMQueueInsertBefore(&lock->procLocks, &proclock->lockLink);
4254  SHMQueueInsertBefore(&(proc->myProcLocks[partition]),
4255  &proclock->procLink);
4256  PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4257  }
4258  else
4259  {
4260  PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4261  Assert((proclock->holdMask & ~lock->grantMask) == 0);
4262  }
4263 
4264  /*
4265  * lock->nRequested and lock->requested[] count the total number of
4266  * requests, whether granted or waiting, so increment those immediately.
4267  */
4268  lock->nRequested++;
4269  lock->requested[lockmode]++;
4270  Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4271 
4272  /*
4273  * We shouldn't already hold the desired lock.
4274  */
4275  if (proclock->holdMask & LOCKBIT_ON(lockmode))
4276  elog(ERROR, "lock %s on object %u/%u/%u is already held",
4277  lockMethodTable->lockModeNames[lockmode],
4278  lock->tag.locktag_field1, lock->tag.locktag_field2,
4279  lock->tag.locktag_field3);
4280 
4281  /*
4282  * We ignore any possible conflicts and just grant ourselves the lock. Not
4283  * only because we don't bother, but also to avoid deadlocks when
4284  * switching from standby to normal mode. See function comment.
4285  */
4286  GrantLock(lock, proclock, lockmode);
4287 
4288  /*
4289  * Bump strong lock count, to make sure any fast-path lock requests won't
4290  * be granted without consulting the primary lock table.
4291  */
4292  if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4293  {
4294  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4295 
4297  FastPathStrongRelationLocks->count[fasthashcode]++;
4299  }
4300 
4301  LWLockRelease(partitionLock);
4302 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:932
Definition: lwlock.h:31
int errhint(const char *fmt,...)
Definition: elog.c:1071
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:232
int LOCKMODE
Definition: lockdefs.h:26
int nRequested
Definition: lock.h:308
LOCKMASK holdMask
Definition: lock.h:365
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1555
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:268
LOCKTAG tag
Definition: lock.h:300
Definition: lock.h:164
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
SHM_QUEUE lockLink
Definition: lock.h:367
int errcode(int sqlerrcode)
Definition: elog.c:610
#define MemSet(start, val, len)
Definition: c.h:949
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:262
#define LockHashPartition(hashcode)
Definition: lock.h:512
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define lengthof(array)
Definition: c.h:675
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:310
PROC_QUEUE waitProcs
Definition: lock.h:306
LOCKTAG locktag
Definition: lock.c:160
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:565
void ProcQueueInit(PROC_QUEUE *queue)
Definition: proc.c:1033
uint32 locktag_field2
Definition: lock.h:167
unsigned int uint32
Definition: c.h:374
int granted[MAX_LOCKMODES]
Definition: lock.h:309
Definition: lock.h:297
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:873
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:517
LOCKMASK waitMask
Definition: lock.h:304
uint16 LOCKMETHODID
Definition: lock.h:124
SHM_QUEUE procLocks
Definition: lock.h:305
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define SpinLockRelease(lock)
Definition: spin.h:64
int requested[MAX_LOCKMODES]
Definition: lock.h:307
#define MAX_LOCKMODES
Definition: lock.h:84
SHM_QUEUE procLink
Definition: lock.h:368
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 locktag_lockmethodid
Definition: lock.h:171
PGPROC * myProc
Definition: lock.h:355
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:303
Definition: lock.h:358
int errmsg(const char *fmt,...)
Definition: elog.c:824
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
#define elog(elevel,...)
Definition: elog.h:214
LOCK * myLock
Definition: lock.h:354
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:196
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
uint32 locktag_field1
Definition: lock.h:166
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:112
uint32 locktag_field3
Definition: lock.h:168
PGPROC * lockGroupLeader
Definition: proc.h:239
const char *const * lockModeNames
Definition: lock.h:114
PGPROC * groupLeader
Definition: lock.h:364
LOCKMASK releaseMask
Definition: lock.h:366

◆ lock_twophase_standby_recover()

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

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

4311 {
4312  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4313  LOCKTAG *locktag;
4314  LOCKMODE lockmode;
4315  LOCKMETHODID lockmethodid;
4316 
4317  Assert(len == sizeof(TwoPhaseLockRecord));
4318  locktag = &rec->locktag;
4319  lockmode = rec->lockmode;
4320  lockmethodid = locktag->locktag_lockmethodid;
4321 
4322  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4323  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4324 
4325  if (lockmode == AccessExclusiveLock &&
4326  locktag->locktag_type == LOCKTAG_RELATION)
4327  {
4329  locktag->locktag_field1 /* dboid */ ,
4330  locktag->locktag_field2 /* reloid */ );
4331  }
4332 }
int LOCKMODE
Definition: lockdefs.h:26
Definition: lock.h:164
#define lengthof(array)
Definition: c.h:675
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
uint32 locktag_field2
Definition: lock.h:167
uint16 LOCKMETHODID
Definition: lock.h:124
uint8 locktag_type
Definition: lock.h:170
#define Assert(condition)
Definition: c.h:745
uint8 locktag_lockmethodid
Definition: lock.h:171
#define AccessExclusiveLock
Definition: lockdefs.h:45
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:651
#define elog(elevel,...)
Definition: elog.h:214
static const LockMethod LockMethods[]
Definition: lock.c:150
uint32 locktag_field1
Definition: lock.h:166
LOCKMODE lockmode
Definition: lock.c:161

◆ LockAcquire()

LockAcquireResult LockAcquire ( const LOCKTAG locktag,
LOCKMODE  lockmode,
bool  sessionLock,
bool  dontWait 
)

◆ LockAcquireExtended()

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

Definition at line 771 of file lock.c.

References AbortStrongLockAcquire(), AccessExclusiveLock, Assert, BeginStrongLockAcquire(), ConflictsWithRelationFastPath, LockMethodData::conflictTab, FastPathStrongRelationLockData::count, CurrentResourceOwner, EligibleForRelationFastPath, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FastPathGrantRelationLock(), FastPathLocalUseCount, FastPathStrongLockHashPartition, FastPathTransferRelationLocks(), FinishStrongLockAcquire(), FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpInfoLock, 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_RELATION_EXTEND, 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(), PROCLOCK::tag, TopMemoryContext, LOCK::waitMask, WaitOnLock(), and XLogStandbyInfoActive.

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

777 {
778  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
779  LockMethod lockMethodTable;
780  LOCALLOCKTAG localtag;
781  LOCALLOCK *locallock;
782  LOCK *lock;
783  PROCLOCK *proclock;
784  bool found;
785  ResourceOwner owner;
786  uint32 hashcode;
787  LWLock *partitionLock;
788  bool found_conflict;
789  bool log_lock = false;
790 
791  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
792  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
793  lockMethodTable = LockMethods[lockmethodid];
794  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
795  elog(ERROR, "unrecognized lock mode: %d", lockmode);
796 
797  if (RecoveryInProgress() && !InRecovery &&
798  (locktag->locktag_type == LOCKTAG_OBJECT ||
799  locktag->locktag_type == LOCKTAG_RELATION) &&
800  lockmode > RowExclusiveLock)
801  ereport(ERROR,
802  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
803  errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
804  lockMethodTable->lockModeNames[lockmode]),
805  errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
806 
807 #ifdef LOCK_DEBUG
808  if (LOCK_DEBUG_ENABLED(locktag))
809  elog(LOG, "LockAcquire: lock [%u,%u] %s",
810  locktag->locktag_field1, locktag->locktag_field2,
811  lockMethodTable->lockModeNames[lockmode]);
812 #endif
813 
814  /* Identify owner for lock */
815  if (sessionLock)
816  owner = NULL;
817  else
818  owner = CurrentResourceOwner;
819 
820  /*
821  * Find or create a LOCALLOCK entry for this lock and lockmode
822  */
823  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
824  localtag.lock = *locktag;
825  localtag.mode = lockmode;
826 
827  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
828  (void *) &localtag,
829  HASH_ENTER, &found);
830 
831  /*
832  * if it's a new locallock object, initialize it
833  */
834  if (!found)
835  {
836  locallock->lock = NULL;
837  locallock->proclock = NULL;
838  locallock->hashcode = LockTagHashCode(&(localtag.lock));
839  locallock->nLocks = 0;
840  locallock->holdsStrongLockCount = false;
841  locallock->lockCleared = false;
842  locallock->numLockOwners = 0;
843  locallock->maxLockOwners = 8;
844  locallock->lockOwners = NULL; /* in case next line fails */
845  locallock->lockOwners = (LOCALLOCKOWNER *)
847  locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
848  }
849  else
850  {
851  /* Make sure there will be room to remember the lock */
852  if (locallock->numLockOwners >= locallock->maxLockOwners)
853  {
854  int newsize = locallock->maxLockOwners * 2;
855 
856  locallock->lockOwners = (LOCALLOCKOWNER *)
857  repalloc(locallock->lockOwners,
858  newsize * sizeof(LOCALLOCKOWNER));
859  locallock->maxLockOwners = newsize;
860  }
861  }
862  hashcode = locallock->hashcode;
863 
864  if (locallockp)
865  *locallockp = locallock;
866 
867  /*
868  * If we already hold the lock, we can just increase the count locally.
869  *
870  * If lockCleared is already set, caller need not worry about absorbing
871  * sinval messages related to the lock's object.
872  */
873  if (locallock->nLocks > 0)
874  {
875  GrantLockLocal(locallock, owner);
876  if (locallock->lockCleared)
878  else
880  }
881 
882  /*
883  * We don't acquire any other heavyweight lock while holding the relation
884  * extension lock. We do allow to acquire the same relation extension
885  * lock more than once but that case won't reach here.
886  */
887  Assert(!IsRelationExtensionLockHeld);
888 
889  /*
890  * We don't acquire any other heavyweight lock while holding the page lock
891  * except for relation extension.
892  */
893  Assert(!IsPageLockHeld ||
894  (locktag->locktag_type == LOCKTAG_RELATION_EXTEND));
895 
896  /*
897  * Prepare to emit a WAL record if acquisition of this lock needs to be
898  * replayed in a standby server.
899  *
900  * Here we prepare to log; after lock is acquired we'll issue log record.
901  * This arrangement simplifies error recovery in case the preparation step
902  * fails.
903  *
904  * Only AccessExclusiveLocks can conflict with lock types that read-only
905  * transactions can acquire in a standby server. Make sure this definition
906  * matches the one in GetRunningTransactionLocks().
907  */
908  if (lockmode >= AccessExclusiveLock &&
909  locktag->locktag_type == LOCKTAG_RELATION &&
910  !RecoveryInProgress() &&
912  {
914  log_lock = true;
915  }
916 
917  /*
918  * Attempt to take lock via fast path, if eligible. But if we remember
919  * having filled up the fast path array, we don't attempt to make any
920  * further use of it until we release some locks. It's possible that some
921  * other backend has transferred some of those locks to the shared hash
922  * table, leaving space free, but it's not worth acquiring the LWLock just
923  * to check. It's also possible that we're acquiring a second or third
924  * lock type on a relation we have already locked using the fast-path, but
925  * for now we don't worry about that case either.
926  */
927  if (EligibleForRelationFastPath(locktag, lockmode) &&
929  {
930  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
931  bool acquired;
932 
933  /*
934  * LWLockAcquire acts as a memory sequencing point, so it's safe to
935  * assume that any strong locker whose increment to
936  * FastPathStrongRelationLocks->counts becomes visible after we test
937  * it has yet to begin to transfer fast-path locks.
938  */
940  if (FastPathStrongRelationLocks->count[fasthashcode] != 0)
941  acquired = false;
942  else
943  acquired = FastPathGrantRelationLock(locktag->locktag_field2,
944  lockmode);
946  if (acquired)
947  {
948  /*
949  * The locallock might contain stale pointers to some old shared
950  * objects; we MUST reset these to null before considering the
951  * lock to be acquired via fast-path.
952  */
953  locallock->lock = NULL;
954  locallock->proclock = NULL;
955  GrantLockLocal(locallock, owner);
956  return LOCKACQUIRE_OK;
957  }
958  }
959 
960  /*
961  * If this lock could potentially have been taken via the fast-path by
962  * some other backend, we must (temporarily) disable further use of the
963  * fast-path for this lock tag, and migrate any locks already taken via
964  * this method to the main lock table.
965  */
966  if (ConflictsWithRelationFastPath(locktag, lockmode))
967  {
968  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
969 
970  BeginStrongLockAcquire(locallock, fasthashcode);
971  if (!FastPathTransferRelationLocks(lockMethodTable, locktag,
972  hashcode))
973  {
975  if (locallock->nLocks == 0)
976  RemoveLocalLock(locallock);
977  if (locallockp)
978  *locallockp = NULL;
979  if (reportMemoryError)
980  ereport(ERROR,
981  (errcode(ERRCODE_OUT_OF_MEMORY),
982  errmsg("out of shared memory"),
983  errhint("You might need to increase max_locks_per_transaction.")));
984  else
985  return LOCKACQUIRE_NOT_AVAIL;
986  }
987  }
988 
989  /*
990  * We didn't find the lock in our LOCALLOCK table, and we didn't manage to
991  * take it via the fast-path, either, so we've got to mess with the shared
992  * lock table.
993  */
994  partitionLock = LockHashPartitionLock(hashcode);
995 
996  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
997 
998  /*
999  * Find or create lock and proclock entries with this tag
1000  *
1001  * Note: if the locallock object already existed, it might have a pointer
1002  * to the lock already ... but we should not assume that that pointer is
1003  * valid, since a lock object with zero hold and request counts can go
1004  * away anytime. So we have to use SetupLockInTable() to recompute the
1005  * lock and proclock pointers, even if they're already set.
1006  */
1007  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
1008  hashcode, lockmode);
1009  if (!proclock)
1010  {
1012  LWLockRelease(partitionLock);
1013  if (locallock->nLocks == 0)
1014  RemoveLocalLock(locallock);
1015  if (locallockp)
1016  *locallockp = NULL;
1017  if (reportMemoryError)
1018  ereport(ERROR,
1019  (errcode(ERRCODE_OUT_OF_MEMORY),
1020  errmsg("out of shared memory"),
1021  errhint("You might need to increase max_locks_per_transaction.")));
1022  else
1023  return LOCKACQUIRE_NOT_AVAIL;
1024  }
1025  locallock->proclock = proclock;
1026  lock = proclock->tag.myLock;
1027  locallock->lock = lock;
1028 
1029  /*
1030  * If lock requested conflicts with locks requested by waiters, must join
1031  * wait queue. Otherwise, check for conflict with already-held locks.
1032  * (That's last because most complex check.)
1033  */
1034  if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
1035  found_conflict = true;
1036  else
1037  found_conflict = LockCheckConflicts(lockMethodTable, lockmode,
1038  lock, proclock);
1039 
1040  if (!found_conflict)
1041  {
1042  /* No conflict with held or previously requested locks */
1043  GrantLock(lock, proclock, lockmode);
1044  GrantLockLocal(locallock, owner);
1045  }
1046  else
1047  {
1048  /*
1049  * We can't acquire the lock immediately. If caller specified no
1050  * blocking, remove useless table entries and return
1051  * LOCKACQUIRE_NOT_AVAIL without waiting.
1052  */
1053  if (dontWait)
1054  {
1056  if (proclock->holdMask == 0)
1057  {
1058  uint32 proclock_hashcode;
1059 
1060  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
1061  SHMQueueDelete(&proclock->lockLink);
1062  SHMQueueDelete(&proclock->procLink);
1064  (void *) &(proclock->tag),
1065  proclock_hashcode,
1066  HASH_REMOVE,
1067  NULL))
1068  elog(PANIC, "proclock table corrupted");
1069  }
1070  else
1071  PROCLOCK_PRINT("LockAcquire: NOWAIT", proclock);
1072  lock->nRequested--;
1073  lock->requested[lockmode]--;
1074  LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
1075  Assert((lock->nRequested > 0) && (lock->requested[lockmode] >= 0));
1076  Assert(lock->nGranted <= lock->nRequested);
1077  LWLockRelease(partitionLock);
1078  if (locallock->nLocks == 0)
1079  RemoveLocalLock(locallock);
1080  if (locallockp)
1081  *locallockp = NULL;
1082  return LOCKACQUIRE_NOT_AVAIL;
1083  }
1084 
1085  /*
1086  * Set bitmask of locks this process already holds on this object.
1087  */
1088  MyProc->heldLocks = proclock->holdMask;
1089 
1090  /*
1091  * Sleep till someone wakes me up.
1092  */
1093 
1094  TRACE_POSTGRESQL_LOCK_WAIT_START(locktag->locktag_field1,
1095  locktag->locktag_field2,
1096  locktag->locktag_field3,
1097  locktag->locktag_field4,
1098  locktag->locktag_type,
1099  lockmode);
1100 
1101  WaitOnLock(locallock, owner);
1102 
1103  TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
1104  locktag->locktag_field2,
1105  locktag->locktag_field3,
1106  locktag->locktag_field4,
1107  locktag->locktag_type,
1108  lockmode);
1109 
1110  /*
1111  * NOTE: do not do any material change of state between here and
1112  * return. All required changes in locktable state must have been
1113  * done when the lock was granted to us --- see notes in WaitOnLock.
1114  */
1115 
1116  /*
1117  * Check the proclock entry status, in case something in the ipc
1118  * communication doesn't work correctly.
1119  */
1120  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
1121  {
1123  PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
1124  LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
1125  /* Should we retry ? */
1126  LWLockRelease(partitionLock);
1127  elog(ERROR, "LockAcquire failed");
1128  }
1129  PROCLOCK_PRINT("LockAcquire: granted", proclock);
1130  LOCK_PRINT("LockAcquire: granted", lock, lockmode);
1131  }
1132 
1133  /*
1134  * Lock state is fully up-to-date now; if we error out after this, no
1135  * special error cleanup is required.
1136  */
1138 
1139  LWLockRelease(partitionLock);
1140 
1141  /*
1142  * Emit a WAL record if acquisition of this lock needs to be replayed in a
1143  * standby server.
1144  */
1145  if (log_lock)
1146  {
1147  /*
1148  * Decode the locktag back to the original values, to avoid sending
1149  * lots of empty bytes with every message. See lock.h to check how a
1150  * locktag is defined for LOCKTAG_RELATION
1151  */
1153  locktag->locktag_field2);
1154  }
1155 
1156  return LOCKACQUIRE_OK;
1157 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:932
PROCLOCKTAG tag
Definition: lock.h:361
uint32 hashcode
Definition: lock.h:421
Definition: lwlock.h:31
static HTAB * LockMethodLocalHash
Definition: lock.c:282
bool holdsStrongLockCount
Definition: lock.h:428
int errhint(const char *fmt,...)
Definition: elog.c:1071
int numLockOwners
Definition: lock.h:425
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1170
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:232
LOCKTAG lock
Definition: lock.h:399
static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2655
LOCKMODE mode
Definition: lock.h:400
PROCLOCK * proclock
Definition: lock.h:423
int nRequested
Definition: lock.h:308
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:365
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1555
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:268
bool InRecovery
Definition: xlog.c:205
static int FastPathLocalUseCount
Definition: lock.c:171
const LOCKMASK * conflictTab
Definition: lock.h:113
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
SHM_QUEUE lockLink
Definition: lock.h:367
void LogAccessExclusiveLock(Oid dbOid, Oid relOid)
Definition: standby.c:1061
int errcode(int sqlerrcode)
Definition: elog.c:610
#define MemSet(start, val, len)
Definition: c.h:949
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:262
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define lengthof(array)
Definition: c.h:675
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
#define LOG
Definition: elog.h:26
bool RecoveryInProgress(void)
Definition: xlog.c:8074
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:226
#define PANIC
Definition: elog.h:53
int maxLockOwners
Definition: lock.h:426
int nGranted
Definition: lock.h:310
static void WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1814
uint16 locktag_field4
Definition: lock.h:169
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1367
static void FinishStrongLockAcquire(void)
Definition: lock.c:1747
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:565
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
#define RowExclusiveLock
Definition: lockdefs.h:38
void LogAccessExclusiveLockPrepare(void)
Definition: standby.c:1078
void AbortStrongLockAcquire(void)
Definition: lock.c:1757
uint32 locktag_field2
Definition: lock.h:167
unsigned int uint32
Definition: c.h:374
Definition: lock.h:297
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:517
MemoryContext TopMemoryContext
Definition: mcxt.c:44
LOCKMASK waitMask
Definition: lock.h:304
uint16 LOCKMETHODID
Definition: lock.h:124
int requested[MAX_LOCKMODES]
Definition: lock.h:307
SHM_QUEUE procLink
Definition: lock.h:368
static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode)
Definition: lock.c:1721
#define XLogStandbyInfoActive()
Definition: xlog.h:205
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define ereport(elevel,...)
Definition: elog.h:144
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1420
uint8 locktag_type
Definition: lock.h:170
#define Assert(condition)
Definition: c.h:745
LOCALLOCKOWNER * lockOwners
Definition: lock.h:427
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
LOCK * lock
Definition: lock.h:422
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
uint8 locktag_lockmethodid
Definition: lock.h:171
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: lock.h:358
int64 nLocks
Definition: lock.h:424
int errmsg(const char *fmt,...)
Definition: elog.c:824
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define elog(elevel,...)
Definition: elog.h:214
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
LOCK * myLock
Definition: lock.h:354
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
LWLock fpInfoLock
Definition: proc.h:228
static bool FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag, uint32 hashcode)
Definition: lock.c:2722
uint32 locktag_field1
Definition: lock.h:166
uint32 locktag_field3
Definition: lock.h:168
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1689
bool lockCleared
Definition: lock.h:429
const char *const * lockModeNames
Definition: lock.h:114
LOCKMASK heldLocks
Definition: proc.h:173
int numLockModes
Definition: lock.h:112

◆ LockCheckConflicts()

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

Definition at line 1420 of file lock.c.

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

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

1424 {
1425  int numLockModes = lockMethodTable->numLockModes;
1426  LOCKMASK myLocks;
1427  int conflictMask = lockMethodTable->conflictTab[lockmode];
1428  int conflictsRemaining[MAX_LOCKMODES];
1429  int totalConflictsRemaining = 0;
1430  int i;
1431  SHM_QUEUE *procLocks;
1432  PROCLOCK *otherproclock;
1433 
1434  /*
1435  * first check for global conflicts: If no locks conflict with my request,
1436  * then I get the lock.
1437  *
1438  * Checking for conflict: lock->grantMask represents the types of
1439  * currently held locks. conflictTable[lockmode] has a bit set for each
1440  * type of lock that conflicts with request. Bitwise compare tells if
1441  * there is a conflict.
1442  */
1443  if (!(conflictMask & lock->grantMask))
1444  {
1445  PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1446  return false;
1447  }
1448 
1449  /*
1450  * Rats. Something conflicts. But it could still be my own lock, or a
1451  * lock held by another member of my locking group. First, figure out how
1452  * many conflicts remain after subtracting out any locks I hold myself.
1453  */
1454  myLocks = proclock->holdMask;
1455  for (i = 1; i <= numLockModes; i++)
1456  {
1457  if ((conflictMask & LOCKBIT_ON(i)) == 0)
1458  {
1459  conflictsRemaining[i] = 0;
1460  continue;
1461  }
1462  conflictsRemaining[i] = lock->granted[i];
1463  if (myLocks & LOCKBIT_ON(i))
1464  --conflictsRemaining[i];
1465  totalConflictsRemaining += conflictsRemaining[i];
1466  }
1467 
1468  /* If no conflicts remain, we get the lock. */
1469  if (totalConflictsRemaining == 0)
1470  {
1471  PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1472  return false;
1473  }
1474 
1475  /* If no group locking, it's definitely a conflict. */
1476  if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL)
1477  {
1478  Assert(proclock->tag.myProc == MyProc);
1479  PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1480  proclock);
1481  return true;
1482  }
1483 
1484  /*
1485  * The relation extension or page lock conflict even between the group
1486  * members.
1487  */
1488  if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND ||
1489  (LOCK_LOCKTAG(*lock) == LOCKTAG_PAGE))
1490  {
1491  PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)",
1492  proclock);
1493  return true;
1494  }
1495 
1496  /*
1497  * Locks held in conflicting modes by members of our own lock group are
1498  * not real conflicts; we can subtract those out and see if we still have
1499  * a conflict. This is O(N) in the number of processes holding or
1500  * awaiting locks on this object. We could improve that by making the
1501  * shared memory state more complex (and larger) but it doesn't seem worth
1502  * it.
1503  */
1504  procLocks = &(lock->procLocks);
1505  otherproclock = (PROCLOCK *)
1506  SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink));
1507  while (otherproclock != NULL)
1508  {
1509  if (proclock != otherproclock &&
1510  proclock->groupLeader == otherproclock->groupLeader &&
1511  (otherproclock->holdMask & conflictMask) != 0)
1512  {
1513  int intersectMask = otherproclock->holdMask & conflictMask;
1514 
1515  for (i = 1; i <= numLockModes; i++)
1516  {
1517  if ((intersectMask & LOCKBIT_ON(i)) != 0)
1518  {
1519  if (conflictsRemaining[i] <= 0)
1520  elog(PANIC, "proclocks held do not match lock");
1521  conflictsRemaining[i]--;
1522  totalConflictsRemaining--;
1523  }
1524  }
1525 
1526  if (totalConflictsRemaining == 0)
1527  {
1528  PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1529  proclock);
1530  return false;
1531  }
1532  }
1533  otherproclock = (PROCLOCK *)
1534  SHMQueueNext(procLocks, &otherproclock->lockLink,
1535  offsetof(PROCLOCK, lockLink));
1536  }
1537 
1538  /* Nope, it's a real conflict. */
1539  PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1540  return true;
1541 }
PROCLOCKTAG tag
Definition: lock.h:361
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:365
const LOCKMASK * conflictTab
Definition: lock.h:113
SHM_QUEUE lockLink
Definition: lock.h:367
#define PANIC
Definition: elog.h:53
#define LOCK_LOCKTAG(lock)
Definition: lock.h:314
int granted[MAX_LOCKMODES]
Definition: lock.h:309
SHM_QUEUE procLocks
Definition: lock.h:305
#define MAX_LOCKMODES
Definition: lock.h:84
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:745
int LOCKMASK
Definition: lockdefs.h:25
PGPROC * myProc
Definition: lock.h:355
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:303
Definition: lock.h:358
#define elog(elevel,...)
Definition: elog.h:214
int i
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
PGPROC * lockGroupLeader
Definition: proc.h:239
#define offsetof(type, field)
Definition: c.h:668
PGPROC * groupLeader
Definition: lock.h:364
int numLockModes
Definition: lock.h:112

◆ LockHasWaiters()

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

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

635 {
636  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
637  LockMethod lockMethodTable;
638  LOCALLOCKTAG localtag;
639  LOCALLOCK *locallock;
640  LOCK *lock;
641  PROCLOCK *proclock;
642  LWLock *partitionLock;
643  bool hasWaiters = false;
644 
645  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
646  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
647  lockMethodTable = LockMethods[lockmethodid];
648  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
649  elog(ERROR, "unrecognized lock mode: %d", lockmode);
650 
651 #ifdef LOCK_DEBUG
652  if (LOCK_DEBUG_ENABLED(locktag))
653  elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
654  locktag->locktag_field1, locktag->locktag_field2,
655  lockMethodTable->lockModeNames[lockmode]);
656 #endif
657 
658  /*
659  * Find the LOCALLOCK entry for this lock and lockmode
660  */
661  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
662  localtag.lock = *locktag;
663  localtag.mode = lockmode;
664 
665  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
666  (void *) &localtag,
667  HASH_FIND, NULL);
668 
669  /*
670  * let the caller print its own error message, too. Do not ereport(ERROR).
671  */
672  if (!locallock || locallock->nLocks <= 0)
673  {
674  elog(WARNING, "you don't own a lock of type %s",
675  lockMethodTable->lockModeNames[lockmode]);
676  return false;
677  }
678 
679  /*
680  * Check the shared lock table.
681  */
682  partitionLock = LockHashPartitionLock(locallock->hashcode);
683 
684  LWLockAcquire(partitionLock, LW_SHARED);
685 
686  /*
687  * We don't need to re-find the lock or proclock, since we kept their
688  * addresses in the locallock table, and they couldn't have been removed
689  * while we were holding a lock on them.
690  */
691  lock = locallock->lock;
692  LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
693  proclock = locallock->proclock;
694  PROCLOCK_PRINT("LockHasWaiters: found", proclock);
695 
696  /*
697  * Double-check that we are actually holding a lock of the type we want to
698  * release.
699  */
700  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
701  {
702  PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
703  LWLockRelease(partitionLock);
704  elog(WARNING, "you don't own a lock of type %s",
705  lockMethodTable->lockModeNames[lockmode]);
706  RemoveLocalLock(locallock);
707  return false;
708  }
709 
710  /*
711  * Do the checking.
712  */
713  if ((lockMethodTable->conflictTab[lockmode] & lock->waitMask) != 0)
714  hasWaiters = true;
715 
716  LWLockRelease(partitionLock);
717 
718  return hasWaiters;
719 }
uint32 hashcode
Definition: lock.h:421
Definition: lwlock.h:31
static HTAB * LockMethodLocalHash
Definition: lock.c:282
LOCKTAG lock
Definition: lock.h:399
LOCKMODE mode
Definition: lock.h:400
PROCLOCK * proclock
Definition: lock.h:423
LOCKMASK holdMask
Definition: lock.h:365
const LOCKMASK * conflictTab
Definition: lock.h:113
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
#define MemSet(start, val, len)
Definition: c.h:949
#define lengthof(array)
Definition: c.h:675
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1367
uint32 locktag_field2
Definition: lock.h:167
Definition: lock.h:297
LOCKMASK waitMask
Definition: lock.h:304
uint16 LOCKMETHODID
Definition: lock.h:124
#define WARNING
Definition: elog.h:40
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
LOCK * lock
Definition: lock.h:422
uint8 locktag_lockmethodid
Definition: lock.h:171
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:358
int64 nLocks
Definition: lock.h:424
#define elog(elevel,...)
Definition: elog.h:214
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
uint32 locktag_field1
Definition: lock.h:166
const char *const * lockModeNames
Definition: lock.h:114
int numLockModes
Definition: lock.h:112

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 598 of file lock.c.

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

Referenced by CheckRelationLockedByMe().

599 {
600  LOCALLOCKTAG localtag;
601  LOCALLOCK *locallock;
602 
603  /*
604  * See if there is a LOCALLOCK entry for this lock and lockmode
605  */
606  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
607  localtag.lock = *locktag;
608  localtag.mode = lockmode;
609 
610  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
611  (void *) &localtag,
612  HASH_FIND, NULL);
613 
614  return (locallock && locallock->nLocks > 0);
615 }
static HTAB * LockMethodLocalHash
Definition: lock.c:282
LOCKTAG lock
Definition: lock.h:399
LOCKMODE mode
Definition: lock.h:400
#define MemSet(start, val, len)
Definition: c.h:949
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
int64 nLocks
Definition: lock.h:424

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2579 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2580 {
2582 
2583  Assert(parent != NULL);
2584 
2585  if (locallocks == NULL)
2586  {
2588  LOCALLOCK *locallock;
2589 
2591 
2592  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2593  LockReassignOwner(locallock, parent);
2594  }
2595  else
2596  {
2597  int i;
2598 
2599  for (i = nlocks - 1; i >= 0; i--)
2600  LockReassignOwner(locallocks[i], parent);
2601  }
2602 }
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2609
static HTAB * LockMethodLocalHash
Definition: lock.c:282
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition: resowner.c:763
#define Assert(condition)
Definition: c.h:745
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ LockRelease()

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

Definition at line 1975 of file lock.c.

References Assert, CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FastPathLocalUseCount, FastPathUnGrantRelationLock(), PGPROC::fpInfoLock, 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().

1976 {
1977  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
1978  LockMethod lockMethodTable;
1979  LOCALLOCKTAG localtag;
1980  LOCALLOCK *locallock;
1981  LOCK *lock;
1982  PROCLOCK *proclock;
1983  LWLock *partitionLock;
1984  bool wakeupNeeded;
1985 
1986  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
1987  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
1988  lockMethodTable = LockMethods[lockmethodid];
1989  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
1990  elog(ERROR, "unrecognized lock mode: %d", lockmode);
1991 
1992 #ifdef LOCK_DEBUG
1993  if (LOCK_DEBUG_ENABLED(locktag))
1994  elog(LOG, "LockRelease: lock [%u,%u] %s",
1995  locktag->locktag_field1, locktag->locktag_field2,
1996  lockMethodTable->lockModeNames[lockmode]);
1997 #endif
1998 
1999  /*
2000  * Find the LOCALLOCK entry for this lock and lockmode
2001  */
2002  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
2003  localtag.lock = *locktag;
2004  localtag.mode = lockmode;
2005 
2006  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
2007  (void *) &localtag,
2008  HASH_FIND, NULL);
2009 
2010  /*
2011  * let the caller print its own error message, too. Do not ereport(ERROR).
2012  */
2013  if (!locallock || locallock->nLocks <= 0)
2014  {
2015  elog(WARNING, "you don't own a lock of type %s",
2016  lockMethodTable->lockModeNames[lockmode]);
2017  return false;
2018  }
2019 
2020  /*
2021  * Decrease the count for the resource owner.
2022  */
2023  {
2024  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2025  ResourceOwner owner;
2026  int i;
2027 
2028  /* Identify owner for lock */
2029  if (sessionLock)
2030  owner = NULL;
2031  else
2032  owner = CurrentResourceOwner;
2033 
2034  for (i = locallock->numLockOwners - 1; i >= 0; i--)
2035  {
2036  if (lockOwners[i].owner == owner)
2037  {
2038  Assert(lockOwners[i].nLocks > 0);
2039  if (--lockOwners[i].nLocks == 0)
2040  {
2041  if (owner != NULL)
2042  ResourceOwnerForgetLock(owner, locallock);
2043  /* compact out unused slot */
2044  locallock->numLockOwners--;
2045  if (i < locallock->numLockOwners)
2046  lockOwners[i] = lockOwners[locallock->numLockOwners];
2047  }
2048  break;
2049  }
2050  }
2051  if (i < 0)
2052  {
2053  /* don't release a lock belonging to another owner */
2054  elog(WARNING, "you don't own a lock of type %s",
2055  lockMethodTable->lockModeNames[lockmode]);
2056  return false;
2057  }
2058  }
2059 
2060  /*
2061  * Decrease the total local count. If we're still holding the lock, we're
2062  * done.
2063  */
2064  locallock->nLocks--;
2065 
2066  if (locallock->nLocks > 0)
2067  return true;
2068 
2069  /*
2070  * At this point we can no longer suppose we are clear of invalidation
2071  * messages related to this lock. Although we'll delete the LOCALLOCK
2072  * object before any intentional return from this routine, it seems worth
2073  * the trouble to explicitly reset lockCleared right now, just in case
2074  * some error prevents us from deleting the LOCALLOCK.
2075  */
2076  locallock->lockCleared = false;
2077 
2078  /* Attempt fast release of any lock eligible for the fast path. */
2079  if (EligibleForRelationFastPath(locktag, lockmode) &&
2081  {
2082  bool released;
2083 
2084  /*
2085  * We might not find the lock here, even if we originally entered it
2086  * here. Another backend may have moved it to the main table.
2087  */
2089  released = FastPathUnGrantRelationLock(locktag->locktag_field2,
2090  lockmode);
2092  if (released)
2093  {
2094  RemoveLocalLock(locallock);
2095  return true;
2096  }
2097  }
2098 
2099  /*
2100  * Otherwise we've got to mess with the shared lock table.
2101  */
2102  partitionLock = LockHashPartitionLock(locallock->hashcode);
2103 
2104  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2105 
2106  /*
2107  * Normally, we don't need to re-find the lock or proclock, since we kept
2108  * their addresses in the locallock table, and they couldn't have been
2109  * removed while we were holding a lock on them. But it's possible that
2110  * the lock was taken fast-path and has since been moved to the main hash
2111  * table by another backend, in which case we will need to look up the
2112  * objects here. We assume the lock field is NULL if so.
2113  */
2114  lock = locallock->lock;
2115  if (!lock)
2116  {
2117  PROCLOCKTAG proclocktag;
2118 
2119  Assert(EligibleForRelationFastPath(locktag, lockmode));
2121  (const void *) locktag,
2122  locallock->hashcode,
2123  HASH_FIND,
2124  NULL);
2125  if (!lock)
2126  elog(ERROR, "failed to re-find shared lock object");
2127  locallock->lock = lock;
2128 
2129  proclocktag.myLock = lock;
2130  proclocktag.myProc = MyProc;
2132  (void *) &proclocktag,
2133  HASH_FIND,
2134  NULL);
2135  if (!locallock->proclock)
2136  elog(ERROR, "failed to re-find shared proclock object");
2137  }
2138  LOCK_PRINT("LockRelease: found", lock, lockmode);
2139  proclock = locallock->proclock;
2140  PROCLOCK_PRINT("LockRelease: found", proclock);
2141 
2142  /*
2143  * Double-check that we are actually holding a lock of the type we want to
2144  * release.
2145  */
2146  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2147  {
2148  PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
2149  LWLockRelease(partitionLock);
2150  elog(WARNING, "you don't own a lock of type %s",
2151  lockMethodTable->lockModeNames[lockmode]);
2152  RemoveLocalLock(locallock);
2153  return false;
2154  }
2155 
2156  /*
2157  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2158  */
2159  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2160 
2161  CleanUpLock(lock, proclock,
2162  lockMethodTable, locallock->hashcode,
2163  wakeupNeeded);
2164 
2165  LWLockRelease(partitionLock);
2166 
2167  RemoveLocalLock(locallock);
2168  return true;
2169 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:932
uint32 hashcode
Definition: lock.h:421
Definition: lwlock.h:31
static HTAB * LockMethodLocalHash
Definition: lock.c:282
int numLockOwners
Definition: lock.h:425
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2692
LOCKTAG lock
Definition: lock.h:399
LOCKMODE mode
Definition: lock.h:400
PROCLOCK * proclock
Definition: lock.h:423
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:365
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
static int FastPathLocalUseCount
Definition: lock.c:171
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
#define MemSet(start, val, len)
Definition: c.h:949
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define lengthof(array)
Definition: c.h:675
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
#define LOG
Definition: elog.h:26
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:226
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1367
uint32 locktag_field2
Definition: lock.h:167
Definition: lock.h:297
uint16 LOCKMETHODID
Definition: lock.h:124
#define WARNING
Definition: elog.h:40
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:977
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define Assert(condition)
Definition: c.h:745
static HTAB * LockMethodLockHash
Definition: lock.c:280
LOCALLOCKOWNER * lockOwners
Definition: lock.h:427
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
LOCK * lock
Definition: lock.h:422
uint8 locktag_lockmethodid
Definition: lock.h:171
PGPROC * myProc
Definition: lock.h:355
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:358
int64 nLocks
Definition: lock.h:424
#define elog(elevel,...)
Definition: elog.h:214
int i
LOCK * myLock
Definition: lock.h:354
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1578
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
LWLock fpInfoLock
Definition: proc.h:228
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1635
uint32 locktag_field1
Definition: lock.h:166
bool lockCleared
Definition: lock.h:429
const char *const * lockModeNames
Definition: lock.h:114
int numLockModes
Definition: lock.h:112

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2180 of file lock.c.

References Assert, CleanUpLock(), DEFAULT_LOCKMETHOD, EligibleForRelationFastPath, elog, ERROR, FastPathUnGrantRelationLock(), PGPROC::fpInfoLock, 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().

2181 {
2183  LockMethod lockMethodTable;
2184  int i,
2185  numLockModes;
2186  LOCALLOCK *locallock;
2187  LOCK *lock;
2188  PROCLOCK *proclock;
2189  int partition;
2190  bool have_fast_path_lwlock = false;
2191 
2192  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2193  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2194  lockMethodTable = LockMethods[lockmethodid];
2195 
2196 #ifdef LOCK_DEBUG
2197  if (*(lockMethodTable->trace_flag))
2198  elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2199 #endif
2200 
2201  /*
2202  * Get rid of our fast-path VXID lock, if appropriate. Note that this is
2203  * the only way that the lock we hold on our own VXID can ever get
2204  * released: it is always and only released when a toplevel transaction
2205  * ends.
2206  */
2207  if (lockmethodid == DEFAULT_LOCKMETHOD)
2209 
2210  numLockModes = lockMethodTable->numLockModes;
2211 
2212  /*
2213  * First we run through the locallock table and get rid of unwanted
2214  * entries, then we scan the process's proclocks and get rid of those. We
2215  * do this separately because we may have multiple locallock entries
2216  * pointing to the same proclock, and we daren't end up with any dangling
2217  * pointers. Fast-path locks are cleaned up during the locallock table
2218  * scan, though.
2219  */
2221 
2222  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2223  {
2224  /*
2225  * If the LOCALLOCK entry is unused, we must've run out of shared
2226  * memory while trying to set up this lock. Just forget the local
2227  * entry.
2228  */
2229  if (locallock->nLocks == 0)
2230  {
2231  RemoveLocalLock(locallock);
2232  continue;
2233  }
2234 
2235  /* Ignore items that are not of the lockmethod to be removed */
2236  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2237  continue;
2238 
2239  /*
2240  * If we are asked to release all locks, we can just zap the entry.
2241  * Otherwise, must scan to see if there are session locks. We assume
2242  * there is at most one lockOwners entry for session locks.
2243  */
2244  if (!allLocks)
2245  {
2246  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2247 
2248  /* If session lock is above array position 0, move it down to 0 */
2249  for (i = 0; i < locallock->numLockOwners; i++)
2250  {
2251  if (lockOwners[i].owner == NULL)
2252  lockOwners[0] = lockOwners[i];
2253  else
2254  ResourceOwnerForgetLock(lockOwners[i].owner, locallock);
2255  }
2256 
2257  if (locallock->numLockOwners > 0 &&
2258  lockOwners[0].owner == NULL &&
2259  lockOwners[0].nLocks > 0)
2260  {
2261  /* Fix the locallock to show just the session locks */
2262  locallock->nLocks = lockOwners[0].nLocks;
2263  locallock->numLockOwners = 1;
2264  /* We aren't deleting this locallock, so done */
2265  continue;
2266  }
2267  else
2268  locallock->numLockOwners = 0;
2269  }
2270 
2271  /*
2272  * If the lock or proclock pointers are NULL, this lock was taken via
2273  * the relation fast-path (and is not known to have been transferred).
2274  */
2275  if (locallock->proclock == NULL || locallock->lock == NULL)
2276  {
2277  LOCKMODE lockmode = locallock->tag.mode;
2278  Oid relid;
2279 
2280  /* Verify that a fast-path lock is what we've got. */
2281  if (!EligibleForRelationFastPath(&locallock->tag.lock, lockmode))
2282  elog(PANIC, "locallock table corrupted");
2283 
2284  /*
2285  * If we don't currently hold the LWLock that protects our
2286  * fast-path data structures, we must acquire it before attempting
2287  * to release the lock via the fast-path. We will continue to
2288  * hold the LWLock until we're done scanning the locallock table,
2289  * unless we hit a transferred fast-path lock. (XXX is this
2290  * really such a good idea? There could be a lot of entries ...)
2291  */
2292  if (!have_fast_path_lwlock)
2293  {
2295  have_fast_path_lwlock = true;
2296  }
2297 
2298  /* Attempt fast-path release. */
2299  relid = locallock->tag.lock.locktag_field2;
2300  if (FastPathUnGrantRelationLock(relid, lockmode))
2301  {
2302  RemoveLocalLock(locallock);
2303  continue;
2304  }
2305 
2306  /*
2307  * Our lock, originally taken via the fast path, has been
2308  * transferred to the main lock table. That's going to require
2309  * some extra work, so release our fast-path lock before starting.
2310  */
2312  have_fast_path_lwlock = false;
2313 
2314  /*
2315  * Now dump the lock. We haven't got a pointer to the LOCK or
2316  * PROCLOCK in this case, so we have to handle this a bit
2317  * differently than a normal lock release. Unfortunately, this
2318  * requires an extra LWLock acquire-and-release cycle on the
2319  * partitionLock, but hopefully it shouldn't happen often.
2320  */
2321  LockRefindAndRelease(lockMethodTable, MyProc,
2322  &locallock->tag.lock, lockmode, false);
2323  RemoveLocalLock(locallock);
2324  continue;
2325  }
2326 
2327  /* Mark the proclock to show we need to release this lockmode */
2328  if (locallock->nLocks > 0)
2329  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
2330 
2331  /* And remove the locallock hashtable entry */
2332  RemoveLocalLock(locallock);
2333  }
2334 
2335  /* Done with the fast-path data structures */
2336  if (have_fast_path_lwlock)
2338 
2339  /*
2340  * Now, scan each lock partition separately.
2341  */
2342  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
2343  {
2344  LWLock *partitionLock;
2345  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
2346  PROCLOCK *nextplock;
2347 
2348  partitionLock = LockHashPartitionLockByIndex(partition);
2349 
2350  /*
2351  * If the proclock list for this partition is empty, we can skip
2352  * acquiring the partition lock. This optimization is trickier than
2353  * it looks, because another backend could be in process of adding
2354  * something to our proclock list due to promoting one of our
2355  * fast-path locks. However, any such lock must be one that we
2356  * decided not to delete above, so it's okay to skip it again now;
2357  * we'd just decide not to delete it again. We must, however, be
2358  * careful to re-fetch the list header once we've acquired the
2359  * partition lock, to be sure we have a valid, up-to-date pointer.
2360  * (There is probably no significant risk if pointer fetch/store is
2361  * atomic, but we don't wish to assume that.)
2362  *
2363  * XXX This argument assumes that the locallock table correctly
2364  * represents all of our fast-path locks. While allLocks mode
2365  * guarantees to clean up all of our normal locks regardless of the
2366  * locallock situation, we lose that guarantee for fast-path locks.
2367  * This is not ideal.
2368  */
2369  if (SHMQueueNext(procLocks, procLocks,
2370  offsetof(PROCLOCK, procLink)) == NULL)
2371  continue; /* needn't examine this partition */
2372 
2373  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2374 
2375  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2376  offsetof(PROCLOCK, procLink));
2377  proclock;
2378  proclock = nextplock)
2379  {
2380  bool wakeupNeeded = false;
2381 
2382  /* Get link first, since we may unlink/delete this proclock */
2383  nextplock = (PROCLOCK *)
2384  SHMQueueNext(procLocks, &proclock->procLink,
2385  offsetof(PROCLOCK, procLink));
2386 
2387  Assert(proclock->tag.myProc == MyProc);
2388 
2389  lock = proclock->tag.myLock;
2390 
2391  /* Ignore items that are not of the lockmethod to be removed */
2392  if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
2393  continue;
2394 
2395  /*
2396  * In allLocks mode, force release of all locks even if locallock
2397  * table had problems
2398  */
2399  if (allLocks)
2400  proclock->releaseMask = proclock->holdMask;
2401  else
2402  Assert((proclock->releaseMask & ~proclock->holdMask) == 0);
2403 
2404  /*
2405  * Ignore items that have nothing to be released, unless they have
2406  * holdMask == 0 and are therefore recyclable
2407  */
2408  if (proclock->releaseMask == 0 && proclock->holdMask != 0)
2409  continue;
2410 
2411  PROCLOCK_PRINT("LockReleaseAll", proclock);
2412  LOCK_PRINT("LockReleaseAll", lock, 0);
2413  Assert(lock->nRequested >= 0);
2414  Assert(lock->nGranted >= 0);
2415  Assert(lock->nGranted <= lock->nRequested);
2416  Assert((proclock->holdMask & ~lock->grantMask) == 0);
2417 
2418  /*
2419  * Release the previously-marked lock modes
2420  */
2421  for (i = 1; i <= numLockModes; i++)
2422  {
2423  if (proclock->releaseMask & LOCKBIT_ON(i))
2424  wakeupNeeded |= UnGrantLock(lock, i, proclock,
2425  lockMethodTable);
2426  }
2427  Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
2428  Assert(lock->nGranted <= lock->nRequested);
2429  LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2430 
2431  proclock->releaseMask = 0;
2432 
2433  /* CleanUpLock will wake up waiters if needed. */
2434  CleanUpLock(lock, proclock,
2435  lockMethodTable,
2436  LockTagHashCode(&lock->tag),
2437  wakeupNeeded);
2438  } /* loop over PROCLOCKs within this partition */
2439 
2440  LWLockRelease(partitionLock);
2441  } /* loop over partitions */
2442 
2443 #ifdef LOCK_DEBUG
2444  if (*(lockMethodTable->trace_flag))
2445  elog(LOG, "LockReleaseAll done");
2446 #endif
2447 }
PROCLOCKTAG tag
Definition: lock.h:361
Definition: lwlock.h:31
LOCALLOCKTAG tag
Definition: lock.h:418
static HTAB * LockMethodLocalHash
Definition: lock.c:282
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3133
void VirtualXactLockTableCleanup(void)
Definition: lock.c:4414
int numLockOwners
Definition: lock.h:425
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2692
LOCKTAG lock
Definition: lock.h:399
int LOCKMODE
Definition: lockdefs.h:26
LOCKMODE mode
Definition: lock.h:400
PROCLOCK * proclock
Definition: lock.h:423
int nRequested
Definition: lock.h:308
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:365
int64 nLocks
Definition: lock.h:412
LOCKTAG tag
Definition: lock.h:300
#define lengthof(array)
Definition: c.h:675
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:226
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:310
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:517
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1367
uint32 locktag_field2
Definition: lock.h:167
Definition: lock.h:297
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:517
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:432
SHM_QUEUE procLink
Definition: lock.h:368
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:977
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define Assert(condition)
Definition: c.h:745
LOCALLOCKOWNER * lockOwners
Definition: lock.h:427
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
LOCK * lock
Definition: lock.h:422
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
PGPROC * myProc
Definition: lock.h:355
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:303
Definition: lock.h:358
int64 nLocks
Definition: lock.h:424
#define elog(elevel,...)
Definition: elog.h:214
int i
const bool * trace_flag
Definition: lock.h:115
LOCK * myLock
Definition: lock.h:354
struct ResourceOwnerData * owner
Definition: lock.h:411
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1578
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:196
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
LWLock fpInfoLock
Definition: proc.h:228
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1635
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define offsetof(type, field)
Definition: c.h:668
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:115
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:313
int numLockModes
Definition: lock.h:112
LOCKMASK releaseMask
Definition: lock.h:366

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2484 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2485 {
2486  if (locallocks == NULL)
2487  {
2489  LOCALLOCK *locallock;
2490 
2492 
2493  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2494  ReleaseLockIfHeld(locallock, false);
2495  }
2496  else
2497  {
2498  int i;
2499 
2500  for (i = nlocks - 1; i >= 0; i--)
2501  ReleaseLockIfHeld(locallocks[i], false);
2502  }
2503 }
static HTAB * LockMethodLocalHash
Definition: lock.c:282
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2519
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

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

2455 {
2457  LOCALLOCK *locallock;
2458 
2459  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2460  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2461 
2463 
2464  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2465  {
2466  /* Ignore items that are not of the specified lock method */
2467  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2468  continue;
2469 
2470  ReleaseLockIfHeld(locallock, true);
2471  }
2472 }
static HTAB * LockMethodLocalHash
Definition: lock.c:282
#define lengthof(array)
Definition: c.h:675
#define ERROR
Definition: elog.h:43
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2519
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:432
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1401
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1391
#define elog(elevel,...)
Definition: elog.h:214
static const LockMethod LockMethods[]
Definition: lock.c:150
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

◆ LockShmemSize()

Size LockShmemSize ( void  )

Definition at line 3532 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

3533 {
3534  Size size = 0;
3535  long max_table_size;
3536 
3537  /* lock hash table */
3538  max_table_size = NLOCKENTS();
3539  size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3540 
3541  /* proclock hash table */
3542  max_table_size *= 2;
3543  size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3544 
3545  /*
3546  * Since NLOCKENTS is only an estimate, add 10% safety margin.
3547  */
3548  size = add_size(size, size / 10);
3549 
3550  return size;
3551 }
#define NLOCKENTS()
Definition: lock.c:56
Definition: lock.h:297
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:745
Size add_size(Size s1, Size s2)
Definition: shmem.c:498
size_t Size
Definition: c.h:473
Definition: lock.h:358

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 517 of file lock.c.

References get_hash_value().

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

518 {
519  return get_hash_value(LockMethodLockHash, (const void *) locktag);
520 }
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:873
static HTAB * LockMethodLockHash
Definition: lock.c:280

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

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

4558 {
4559  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4560  LOCK *lock;
4561  bool found;
4562  uint32 hashcode;
4563  LWLock *partitionLock;
4564  int waiters = 0;
4565 
4566  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4567  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4568 
4569  hashcode = LockTagHashCode(locktag);
4570  partitionLock = LockHashPartitionLock(hashcode);
4571  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4572 
4574  (const void *) locktag,
4575  hashcode,
4576  HASH_FIND,
4577  &found);
4578  if (found)
4579  {
4580  Assert(lock != NULL);
4581  waiters = lock->nRequested;
4582  }
4583  LWLockRelease(partitionLock);
4584 
4585  return waiters;
4586 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:932
Definition: lwlock.h:31
int nRequested
Definition: lock.h:308
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
#define lengthof(array)
Definition: c.h:675
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:374
Definition: lock.h:297
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:517
uint16 LOCKMETHODID
Definition: lock.h:124
#define Assert(condition)
Definition: c.h:745
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 locktag_lockmethodid
Definition: lock.h:171
#define elog(elevel,...)
Definition: elog.h:214
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

Definition at line 1799 of file lock.c.

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

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

1800 {
1801  Assert(locallock->nLocks > 0);
1802  locallock->lockCleared = true;
1803 }
#define Assert(condition)
Definition: c.h:745
int64 nLocks
Definition: lock.h:424
bool lockCleared
Definition: lock.h:429

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

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

3341 {
3342  PGPROC *newproc = TwoPhaseGetDummyProc(xid, false);
3344  LOCALLOCK *locallock;
3345  LOCK *lock;
3346  PROCLOCK *proclock;
3347  PROCLOCKTAG proclocktag;
3348  int partition;
3349 
3350  /* Can't prepare a lock group follower. */
3351  Assert(MyProc->lockGroupLeader == NULL ||
3353 
3354  /* This is a critical section: any error means big trouble */
3356 
3357  /*
3358  * First we run through the locallock table and get rid of unwanted
3359  * entries, then we scan the process's proclocks and transfer them to the
3360  * target proc.
3361  *
3362  * We do this separately because we may have multiple locallock entries
3363  * pointing to the same proclock, and we daren't end up with any dangling
3364  * pointers.
3365  */
3367 
3368  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3369  {
3370  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3371  bool haveSessionLock;
3372  bool haveXactLock;
3373  int i;
3374 
3375  if (locallock->proclock == NULL || locallock->lock == NULL)
3376  {
3377  /*
3378  * We must've run out of shared memory while trying to set up this
3379  * lock. Just forget the local entry.
3380  */
3381  Assert(locallock->nLocks == 0);
3382  RemoveLocalLock(locallock);
3383  continue;
3384  }
3385 
3386  /* Ignore VXID locks */
3387  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3388  continue;
3389 
3390  /* Scan to see whether we hold it at session or transaction level */
3391  haveSessionLock = haveXactLock = false;
3392  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3393  {
3394  if (lockOwners[i].owner == NULL)
3395  haveSessionLock = true;
3396  else
3397  haveXactLock = true;
3398  }
3399 
3400  /* Ignore it if we have only session lock */
3401  if (!haveXactLock)
3402  continue;
3403 
3404  /* This can't happen, because we already checked it */
3405  if (haveSessionLock)
3406  ereport(PANIC,
3407  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3408  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3409 
3410  /* Mark the proclock to show we need to release this lockmode */
3411  if (locallock->nLocks > 0)
3412  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3413 
3414  /* And remove the locallock hashtable entry */
3415  RemoveLocalLock(locallock);
3416  }
3417 
3418  /*
3419  * Now, scan each lock partition separately.
3420  */
3421  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3422  {
3423  LWLock *partitionLock;
3424  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
3425  PROCLOCK *nextplock;
3426 
3427  partitionLock = LockHashPartitionLockByIndex(partition);
3428 
3429  /*
3430  * If the proclock list for this partition is empty, we can skip
3431  * acquiring the partition lock. This optimization is safer than the
3432  * situation in LockReleaseAll, because we got rid of any fast-path
3433  * locks during AtPrepare_Locks, so there cannot be any case where
3434  * another backend is adding something to our lists now. For safety,
3435  * though, we code this the same way as in LockReleaseAll.
3436  */
3437  if (SHMQueueNext(procLocks, procLocks,
3438  offsetof(PROCLOCK, procLink)) == NULL)
3439  continue; /* needn't examine this partition */
3440 
3441  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3442 
3443  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3444  offsetof(PROCLOCK, procLink));
3445  proclock;
3446  proclock = nextplock)
3447  {
3448  /* Get link first, since we may unlink/relink this proclock */
3449  nextplock = (PROCLOCK *)
3450  SHMQueueNext(procLocks, &proclock->procLink,
3451  offsetof(PROCLOCK, procLink));
3452 
3453  Assert(proclock->tag.myProc == MyProc);
3454 
3455  lock = proclock->tag.myLock;
3456 
3457  /* Ignore VXID locks */
3459  continue;
3460 
3461  PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3462  LOCK_PRINT("PostPrepare_Locks", lock, 0);
3463  Assert(lock->nRequested >= 0);
3464  Assert(lock->nGranted >= 0);
3465  Assert(lock->nGranted <= lock->nRequested);
3466  Assert((proclock->holdMask & ~lock->grantMask) == 0);
3467 
3468  /* Ignore it if nothing to release (must be a session lock) */
3469  if (proclock->releaseMask == 0)
3470  continue;
3471 
3472  /* Else we should be releasing all locks */
3473  if (proclock->releaseMask != proclock->holdMask)
3474  elog(PANIC, "we seem to have dropped a bit somewhere");
3475 
3476  /*
3477  * We cannot simply modify proclock->tag.myProc to reassign
3478  * ownership of the lock, because that's part of the hash key and
3479  * the proclock would then be in the wrong hash chain. Instead
3480  * use hash_update_hash_key. (We used to create a new hash entry,
3481  * but that risks out-of-memory failure if other processes are
3482  * busy making proclocks too.) We must unlink the proclock from
3483  * our procLink chain and put it into the new proc's chain, too.
3484  *
3485  * Note: the updated proclock hash key will still belong to the
3486  * same hash partition, cf proclock_hash(). So the partition lock
3487  * we already hold is sufficient for this.
3488  */
3489  SHMQueueDelete(&proclock->procLink);
3490 
3491  /*
3492  * Create the new hash key for the proclock.
3493  */
3494  proclocktag.myLock = lock;
3495  proclocktag.myProc = newproc;
3496 
3497  /*
3498  * Update groupLeader pointer to point to the new proc. (We'd
3499  * better not be a member of somebody else's lock group!)
3500  */
3501  Assert(proclock->groupLeader == proclock->tag.myProc);
3502  proclock->groupLeader = newproc;
3503 
3504  /*
3505  * Update the proclock. We should not find any existing entry for
3506  * the same hash key, since there can be only one entry for any
3507  * given lock with my own proc.
3508  */
3510  (void *) proclock,
3511  (void *) &proclocktag))
3512  elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3513 
3514  /* Re-link into the new proc's proclock list */
3515  SHMQueueInsertBefore(&(newproc->myProcLocks[partition]),
3516  &proclock->procLink);
3517 
3518  PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3519  } /* loop over PROCLOCKs within this partition */
3520 
3521  LWLockRelease(partitionLock);
3522  } /* loop over partitions */
3523 
3524  END_CRIT_SECTION();
3525 }
PROCLOCKTAG tag
Definition: lock.h:361
Definition: lwlock.h:31
LOCALLOCKTAG tag
Definition: lock.h:418
static HTAB * LockMethodLocalHash
Definition: lock.c:282
int numLockOwners
Definition: lock.h:425
LOCKTAG lock
Definition: lock.h:399
LOCKMODE mode
Definition: lock.h:400
PROCLOCK * proclock
Definition: lock.h:423
int nRequested
Definition: lock.h:308
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:365
LOCKTAG tag
Definition: lock.h:300
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
int errcode(int sqlerrcode)
Definition: elog.c:610
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:310
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:517
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1367
Definition: lock.h:297
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:873
SHM_QUEUE procLink
Definition: lock.h:368