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 "utils/timestamp.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)   (LocalTransactionIdIsValid((vxid).localTransactionId))
 
#define VirtualTransactionIdIsPreparedXact(vxid)   ((vxid).backendId == InvalidBackendId)
 
#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 81 of file lock.h.

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

◆ InvalidLocalTransactionId

◆ LOCALLOCK_LOCKMETHOD

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

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

Referenced by CheckAndSetLockHeld().

◆ LocalTransactionIdIsValid

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

Definition at line 70 of file lock.h.

Referenced by GetNextLocalTransactionId(), and VirtualXactLockTableCleanup().

◆ LOCK_LOCKMETHOD

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

Definition at line 315 of file lock.h.

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

◆ LOCK_LOCKTAG

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

Definition at line 316 of file lock.h.

Referenced by FindLockCycleRecurseMember(), and LockCheckConflicts().

◆ LOCKBIT_OFF

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

Definition at line 89 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 516 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 533 of file lock.h.

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

◆ LOCKTAG_LAST_TYPE

#define LOCKTAG_LAST_TYPE   LOCKTAG_ADVISORY

Definition at line 154 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 373 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:130

Definition at line 272 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:129

Definition at line 201 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:129

Definition at line 264 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:129

Definition at line 210 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:129

Definition at line 183 of file lock.h.

Referenced by ATExecDetachPartition(), 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:129

Definition at line 192 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:129

Definition at line 249 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:129

Definition at line 228 of file lock.h.

Referenced by ConditionalXactLockTableWait(), VirtualXactLock(), 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:129

Definition at line 219 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:129

Definition at line 237 of file lock.h.

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

◆ SetInvalidVirtualTransactionId

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

Definition at line 78 of file lock.h.

Referenced by InitPredicateLocks(), and WaitForOlderSnapshots().

◆ USER_LOCKMETHOD

#define USER_LOCKMETHOD   2

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

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

◆ VirtualTransactionIdIsPreparedXact

#define VirtualTransactionIdIsPreparedXact (   vxid)    ((vxid).backendId == InvalidBackendId)

Definition at line 73 of file lock.h.

Referenced by VirtualXactLock().

◆ VirtualTransactionIdIsValid

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 120 of file lock.h.

◆ LockMethodData

◆ LOCKMETHODID

Definition at line 126 of file lock.h.

◆ LOCKTAG

typedef struct LOCKTAG LOCKTAG

◆ LockTagType

typedef enum LockTagType LockTagType

◆ PGPROC

typedef struct PGPROC PGPROC

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

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

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 
LOCKACQUIRE_ALREADY_CLEAR 

Definition at line 491 of file lock.h.

492 {
493  LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
494  LOCKACQUIRE_OK, /* lock successfully acquired */
495  LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
496  LOCKACQUIRE_ALREADY_CLEAR /* incremented count for lock already clear */
LockAcquireResult
Definition: lock.h:491

◆ 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 139 of file lock.h.

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

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )

Definition at line 1756 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

1757 {
1758  uint32 fasthashcode;
1759  LOCALLOCK *locallock = StrongLockInProgress;
1760 
1761  if (locallock == NULL)
1762  return;
1763 
1764  fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1765  Assert(locallock->holdsStrongLockCount == true);
1767  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1768  FastPathStrongRelationLocks->count[fasthashcode]--;
1769  locallock->holdsStrongLockCount = false;
1770  StrongLockInProgress = NULL;
1772 }
uint32 hashcode
Definition: lock.h:423
bool holdsStrongLockCount
Definition: lock.h:430
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:441
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:804

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

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

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

◆ 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:1741
int errhint(const char *fmt,...)
Definition: elog.c:1156
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:4014
LOCKMODE lockmode
Definition: deadlock.c:74
int errcode(int sqlerrcode)
Definition: elog.c:698
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define ERROR
Definition: elog.h:46
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:1090
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define ereport(elevel,...)
Definition: elog.h:157
static DEADLOCK_INFO * deadlockDetails
Definition: deadlock.c:124
const char * pgstat_get_backend_current_activity(int pid, bool checkUser)
uint8 locktag_lockmethodid
Definition: lock.h:173
int errmsg(const char *fmt,...)
Definition: elog.c:909
int i
LOCKTAG locktag
Definition: deadlock.c:73
#define _(x)
Definition: elog.c:89
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 582 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

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

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

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

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

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

◆ GetLockConflicts()

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

Definition at line 2909 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(), max_prepared_xacts, MaxBackends, MemoryContextAlloc(), MyProc, PROCLOCKTAG::myProc, LockMethodData::numLockModes, offsetof, palloc0(), PANIC, ProcGlobal, LOCK::procLocks, SHMQueueNext(), PROCLOCK::tag, TopMemoryContext, VirtualTransactionIdEquals, and VirtualTransactionIdIsValid.

Referenced by ProcSleep(), ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

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

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

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

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

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)

Definition at line 486 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

487 {
488  LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
489 
490  Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
491  return LockMethods[lockmethodid];
492 }
#define lengthof(array)
Definition: c.h:734
uint16 LOCKMETHODID
Definition: lock.h:126
#define Assert(condition)
Definition: c.h:804
static const LockMethod LockMethods[]
Definition: lock.c:150
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:315

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

Definition at line 3560 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(), pg_atomic_read_u64(), PGPROC::pid, LockInstanceData::pid, ProcGlobal, repalloc(), SET_LOCKTAG_RELATION, SET_LOCKTAG_VIRTUALTRANSACTION, LOCK::tag, PROCLOCK::tag, PGPROC::waitLock, PGPROC::waitLockMode, LockInstanceData::waitLockMode, PGPROC::waitStart, and LockInstanceData::waitStart.

Referenced by pg_lock_status().

3561 {
3562  LockData *data;
3563  PROCLOCK *proclock;
3564  HASH_SEQ_STATUS seqstat;
3565  int els;
3566  int el;
3567  int i;
3568 
3569  data = (LockData *) palloc(sizeof(LockData));
3570 
3571  /* Guess how much space we'll need. */
3572  els = MaxBackends;
3573  el = 0;
3574  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3575 
3576  /*
3577  * First, we iterate through the per-backend fast-path arrays, locking
3578  * them one at a time. This might produce an inconsistent picture of the
3579  * system state, but taking all of those LWLocks at the same time seems
3580  * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3581  * matter too much, because none of these locks can be involved in lock
3582  * conflicts anyway - anything that might must be present in the main lock
3583  * table. (For the same reason, we don't sweat about making leaderPid
3584  * completely valid. We cannot safely dereference another backend's
3585  * lockGroupLeader field without holding all lock partition locks, and
3586  * it's not worth that.)
3587  */
3588  for (i = 0; i < ProcGlobal->allProcCount; ++i)
3589  {
3590  PGPROC *proc = &ProcGlobal->allProcs[i];
3591  uint32 f;
3592 
3594 
3595  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
3596  {
3597  LockInstanceData *instance;
3598  uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3599 
3600  /* Skip unallocated slots. */
3601  if (!lockbits)
3602  continue;
3603 
3604  if (el >= els)
3605  {
3606  els += MaxBackends;
3607  data->locks = (LockInstanceData *)
3608  repalloc(data->locks, sizeof(LockInstanceData) * els);
3609  }
3610 
3611  instance = &data->locks[el];
3612  SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3613  proc->fpRelId[f]);
3614  instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3615  instance->waitLockMode = NoLock;
3616  instance->backend = proc->backendId;
3617  instance->lxid = proc->lxid;
3618  instance->pid = proc->pid;
3619  instance->leaderPid = proc->pid;
3620  instance->fastpath = true;
3621 
3622  /*
3623  * Successfully taking fast path lock means there were no
3624  * conflicting locks.
3625  */
3626  instance->waitStart = 0;
3627 
3628  el++;
3629  }
3630 
3631  if (proc->fpVXIDLock)
3632  {
3633  VirtualTransactionId vxid;
3634  LockInstanceData *instance;
3635 
3636  if (el >= els)
3637  {
3638  els += MaxBackends;
3639  data->locks = (LockInstanceData *)
3640  repalloc(data->locks, sizeof(LockInstanceData) * els);
3641  }
3642 
3643  vxid.backendId = proc->backendId;
3645 
3646  instance = &data->locks[el];
3647  SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3648  instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3649  instance->waitLockMode = NoLock;
3650  instance->backend = proc->backendId;
3651  instance->lxid = proc->lxid;
3652  instance->pid = proc->pid;
3653  instance->leaderPid = proc->pid;
3654  instance->fastpath = true;
3655  instance->waitStart = 0;
3656 
3657  el++;
3658  }
3659 
3660  LWLockRelease(&proc->fpInfoLock);
3661  }
3662 
3663  /*
3664  * Next, acquire lock on the entire shared lock data structure. We do
3665  * this so that, at least for locks in the primary lock table, the state
3666  * will be self-consistent.
3667  *
3668  * Since this is a read-only operation, we take shared instead of
3669  * exclusive lock. There's not a whole lot of point to this, because all
3670  * the normal operations require exclusive lock, but it doesn't hurt
3671  * anything either. It will at least allow two backends to do
3672  * GetLockStatusData in parallel.
3673  *
3674  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3675  */
3676  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3678 
3679  /* Now we can safely count the number of proclocks */
3681  if (data->nelements > els)
3682  {
3683  els = data->nelements;
3684  data->locks = (LockInstanceData *)
3685  repalloc(data->locks, sizeof(LockInstanceData) * els);
3686  }
3687 
3688  /* Now scan the tables to copy the data */
3690 
3691  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3692  {
3693  PGPROC *proc = proclock->tag.myProc;
3694  LOCK *lock = proclock->tag.myLock;
3695  LockInstanceData *instance = &data->locks[el];
3696 
3697  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3698  instance->holdMask = proclock->holdMask;
3699  if (proc->waitLock == proclock->tag.myLock)
3700  instance->waitLockMode = proc->waitLockMode;
3701  else
3702  instance->waitLockMode = NoLock;
3703  instance->backend = proc->backendId;
3704  instance->lxid = proc->lxid;
3705  instance->pid = proc->pid;
3706  instance->leaderPid = proclock->groupLeader->pid;
3707  instance->fastpath = false;
3708  instance->waitStart = (TimestampTz) pg_atomic_read_u64(&proc->waitStart);
3709 
3710  el++;
3711  }
3712 
3713  /*
3714  * And release locks. We do this in reverse order for two reasons: (1)
3715  * Anyone else who needs more than one of the locks will be trying to lock
3716  * them in increasing order; we don't want to release the other process
3717  * until it can get all the locks it needs. (2) This avoids O(N^2)
3718  * behavior inside LWLockRelease.
3719  */
3720  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3722 
3723  Assert(el == data->nelements);
3724 
3725  return data;
3726 }
PROCLOCKTAG tag
Definition: lock.h:363
LockInstanceData * locks
Definition: lock.h:460
BackendId backendId
Definition: proc.h:153
#define ExclusiveLock
Definition: lockdefs.h:44
int64 TimestampTz
Definition: timestamp.h:39
LOCKMASK holdMask
Definition: lock.h:367
bool fastpath
Definition: lock.h:454
LOCKMODE waitLockMode
Definition: proc.h:181
LOCKTAG tag
Definition: lock.h:302
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
Definition: lock.h:166
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1382
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
bool fpVXIDLock
Definition: proc.h:243
Definition: lock.h:457
LocalTransactionId localTransactionId
Definition: lock.h:66
LOCKTAG locktag
Definition: lock.h:445
LOCKMODE waitLockMode
Definition: lock.h:447
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
int leaderPid
Definition: lock.h:453
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:521
int MaxBackends
Definition: globals.c:139
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:183
#define NoLock
Definition: lockdefs.h:34
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:74
Oid databaseId
Definition: proc.h:154
unsigned int uint32
Definition: c.h:441
Definition: lock.h:299
LOCK * waitLock
Definition: proc.h:179
TimestampTz waitStart
Definition: lock.h:450
int nelements
Definition: lock.h:459
BackendId backend
Definition: lock.h:448
LocalTransactionId lxid
Definition: lock.h:449
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:242
#define Assert(condition)
Definition: c.h:804
BackendId backendId
Definition: lock.h:65
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition: lock.h:237
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
uint32 allProcCount
Definition: proc.h:336
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
LOCKMASK holdMask
Definition: lock.h:446
PGPROC * myProc
Definition: lock.h:357
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:202
#define LOCKBIT_ON(lockmode)
Definition: lock.h:88
Definition: lock.h:360
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:429
void * palloc(Size size)
Definition: mcxt.c:1062
int i
LOCK * myLock
Definition: lock.h:356
PGPROC * allProcs
Definition: proc.h:318
LWLock fpInfoLock
Definition: proc.h:240
pg_atomic_uint64 waitStart
Definition: proc.h:184
Definition: proc.h:121
int pid
Definition: proc.h:146
LocalTransactionId fpLocalTransactionId
Definition: proc.h:244
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:87
PGPROC * groupLeader
Definition: lock.h:366
LocalTransactionId lxid
Definition: proc.h:143

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 498 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

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

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

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

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

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1785 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

1786 {
1788 }
static LOCALLOCK * awaitedLock
Definition: lock.c:287
static ResourceOwner awaitedOwner
Definition: lock.c:288
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1688

◆ GrantLock()

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

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

1555 {
1556  lock->nGranted++;
1557  lock->granted[lockmode]++;
1558  lock->grantMask |= LOCKBIT_ON(lockmode);
1559  if (lock->granted[lockmode] == lock->requested[lockmode])
1560  lock->waitMask &= LOCKBIT_OFF(lockmode);
1561  proclock->holdMask |= LOCKBIT_ON(lockmode);
1562  LOCK_PRINT("GrantLock", lock, lockmode);
1563  Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1564  Assert(lock->nGranted <= lock->nRequested);
1565 }
int nRequested
Definition: lock.h:310
LOCKMASK holdMask
Definition: lock.h:367
int nGranted
Definition: lock.h:312
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:89
int granted[MAX_LOCKMODES]
Definition: lock.h:311
LOCKMASK waitMask
Definition: lock.h:306
int requested[MAX_LOCKMODES]
Definition: lock.h:309
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define Assert(condition)
Definition: c.h:804
#define LOCKBIT_ON(lockmode)
Definition: lock.h:88
LOCKMASK grantMask
Definition: lock.h:305

◆ 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:139
static EDGE * curConstraints
Definition: deadlock.c:116
MemoryContext TopMemoryContext
Definition: mcxt.c:48
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:1062
static int maxPossibleConstraints
Definition: deadlock.c:123
static int * beforeConstraints
Definition: deadlock.c:107
Definition: proc.h:121

◆ 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, 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  info.keysize = sizeof(LOCKTAG);
423  info.entrysize = sizeof(LOCK);
425 
426  LockMethodLockHash = ShmemInitHash("LOCK hash",
427  init_table_size,
428  max_table_size,
429  &info,
431 
432  /* Assume an average of 2 holders per lock */
433  max_table_size *= 2;
434  init_table_size *= 2;
435 
436  /*
437  * Allocate hash table for PROCLOCK structs. This stores
438  * per-lock-per-holder information.
439  */
440  info.keysize = sizeof(PROCLOCKTAG);
441  info.entrysize = sizeof(PROCLOCK);
442  info.hash = proclock_hash;
444 
445  LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
446  init_table_size,
447  max_table_size,
448  &info,
450 
451  /*
452  * Allocate fast-path structures.
453  */
455  ShmemInitStruct("Fast Path Strong Relation Lock Data",
456  sizeof(FastPathStrongRelationLockData), &found);
457  if (!found)
459 
460  /*
461  * Allocate non-shared hash table for LOCALLOCK structs. This stores lock
462  * counts and resource owner information.
463  *
464  * The non-shared table could already exist in this process (this occurs
465  * when the postmaster is recreating shared memory after a backend crash).
466  * If so, delete and recreate it. (We could simply leave it, since it
467  * ought to be empty in the postmaster, but for safety let's zap it.)
468  */
471 
472  info.keysize = sizeof(LOCALLOCKTAG);
473  info.entrysize = sizeof(LOCALLOCK);
474 
475  LockMethodLocalHash = hash_create("LOCALLOCK hash",
476  16,
477  &info,
479 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:862
static HTAB * LockMethodLocalHash
Definition: lock.c:282
#define HASH_ELEM
Definition: hsearch.h:95
#define SpinLockInit(lock)
Definition: spin.h:60
Size entrysize
Definition: hsearch.h:76
static uint32 proclock_hash(const void *key, Size keysize)
Definition: lock.c:533
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
struct LOCALLOCKTAG LOCALLOCKTAG
#define HASH_PARTITION
Definition: hsearch.h:92
#define NLOCKENTS()
Definition: lock.c:56
struct LOCALLOCK LOCALLOCK
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
long num_partitions
Definition: hsearch.h:68
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:349
struct PROCLOCK PROCLOCK
struct LOCKTAG LOCKTAG
#define HASH_BLOBS
Definition: hsearch.h:97
struct PROCLOCKTAG PROCLOCKTAG
Size keysize
Definition: hsearch.h:75
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:341
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:87
HashValueFunc hash
Definition: hsearch.h:78
#define HASH_FUNCTION
Definition: hsearch.h:98

◆ lock_twophase_postabort()

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

Definition at line 4366 of file lock.c.

References lock_twophase_postcommit().

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

◆ lock_twophase_postcommit()

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

Definition at line 4340 of file lock.c.

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

Referenced by lock_twophase_postabort().

4342 {
4343  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4344  PGPROC *proc = TwoPhaseGetDummyProc(xid, true);
4345  LOCKTAG *locktag;
4346  LOCKMETHODID lockmethodid;
4347  LockMethod lockMethodTable;
4348 
4349  Assert(len == sizeof(TwoPhaseLockRecord));
4350  locktag = &rec->locktag;
4351  lockmethodid = locktag->locktag_lockmethodid;
4352 
4353  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4354  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4355  lockMethodTable = LockMethods[lockmethodid];
4356 
4357  LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4358 }
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3124
Definition: lock.h:166
#define lengthof(array)
Definition: c.h:734
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:46
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:874
uint16 LOCKMETHODID
Definition: lock.h:126
#define Assert(condition)
Definition: c.h:804
uint8 locktag_lockmethodid
Definition: lock.h:173
#define elog(elevel,...)
Definition: elog.h:232
static const LockMethod LockMethods[]
Definition: lock.c:150
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:121

◆ lock_twophase_recover()

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

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

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

◆ lock_twophase_standby_recover()

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

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

4310 {
4311  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4312  LOCKTAG *locktag;
4313  LOCKMODE lockmode;
4314  LOCKMETHODID lockmethodid;
4315 
4316  Assert(len == sizeof(TwoPhaseLockRecord));
4317  locktag = &rec->locktag;
4318  lockmode = rec->lockmode;
4319  lockmethodid = locktag->locktag_lockmethodid;
4320 
4321  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4322  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4323 
4324  if (lockmode == AccessExclusiveLock &&
4325  locktag->locktag_type == LOCKTAG_RELATION)
4326  {
4328  locktag->locktag_field1 /* dboid */ ,
4329  locktag->locktag_field2 /* reloid */ );
4330  }
4331 }
int LOCKMODE
Definition: lockdefs.h:26
Definition: lock.h:166
#define lengthof(array)
Definition: c.h:734
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:46
uint32 locktag_field2
Definition: lock.h:169
uint16 LOCKMETHODID
Definition: lock.h:126
uint8 locktag_type
Definition: lock.h:172
#define Assert(condition)
Definition: c.h:804
uint8 locktag_lockmethodid
Definition: lock.h:173
#define AccessExclusiveLock
Definition: lockdefs.h:45
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:948
#define elog(elevel,...)
Definition: elog.h:232
static const LockMethod LockMethods[]
Definition: lock.c:150
uint32 locktag_field1
Definition: lock.h:168
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 770 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().

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

◆ LockCheckConflicts()

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

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

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

◆ LockHasWaiters()

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

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

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

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

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

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

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2578 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2579 {
2581 
2582  Assert(parent != NULL);
2583 
2584  if (locallocks == NULL)
2585  {
2587  LOCALLOCK *locallock;
2588 
2590 
2591  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2592  LockReassignOwner(locallock, parent);
2593  }
2594  else
2595  {
2596  int i;
2597 
2598  for (i = nlocks - 1; i >= 0; i--)
2599  LockReassignOwner(locallocks[i], parent);
2600  }
2601 }
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2608
static HTAB * LockMethodLocalHash
Definition: lock.c:282
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition: resowner.c:792
#define Assert(condition)
Definition: c.h:804
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
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 1974 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().

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

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

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

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

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2483 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2484 {
2485  if (locallocks == NULL)
2486  {
2488  LOCALLOCK *locallock;
2489 
2491 
2492  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2493  ReleaseLockIfHeld(locallock, false);
2494  }
2495  else
2496  {
2497  int i;
2498 
2499  for (i = nlocks - 1; i >= 0; i--)
2500  ReleaseLockIfHeld(locallocks[i], false);
2501  }
2502 }
static HTAB * LockMethodLocalHash
Definition: lock.c:282
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2518
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
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 2453 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().

2454 {
2456  LOCALLOCK *locallock;
2457 
2458  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2459  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2460 
2462 
2463  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2464  {
2465  /* Ignore items that are not of the specified lock method */
2466  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2467  continue;
2468 
2469  ReleaseLockIfHeld(locallock, true);
2470  }
2471 }
static HTAB * LockMethodLocalHash
Definition: lock.c:282
#define lengthof(array)
Definition: c.h:734
#define ERROR
Definition: elog.h:46
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2518
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:434
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1436
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1426
#define elog(elevel,...)
Definition: elog.h:232
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 3523 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

3524 {
3525  Size size = 0;
3526  long max_table_size;
3527 
3528  /* lock hash table */
3529  max_table_size = NLOCKENTS();
3530  size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3531 
3532  /* proclock hash table */
3533  max_table_size *= 2;
3534  size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3535 
3536  /*
3537  * Since NLOCKENTS is only an estimate, add 10% safety margin.
3538  */
3539  size = add_size(size, size / 10);
3540 
3541  return size;
3542 }
#define NLOCKENTS()
Definition: lock.c:56
Definition: lock.h:299
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:780
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
size_t Size
Definition: c.h:540
Definition: lock.h:360

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 516 of file lock.c.

References get_hash_value().

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

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

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

4572 {
4573  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4574  LOCK *lock;
4575  bool found;
4576  uint32 hashcode;
4577  LWLock *partitionLock;
4578  int waiters = 0;
4579 
4580  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4581  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4582 
4583  hashcode = LockTagHashCode(locktag);
4584  partitionLock = LockHashPartitionLock(hashcode);
4585  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4586 
4588  (const void *) locktag,
4589  hashcode,
4590  HASH_FIND,
4591  &found);
4592  if (found)
4593  {
4594  Assert(lock != NULL);
4595  waiters = lock->nRequested;
4596  }
4597  LWLockRelease(partitionLock);
4598 
4599  return waiters;
4600 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:967
Definition: lwlock.h:31
int nRequested
Definition: lock.h:310
#define LockHashPartitionLock(hashcode)
Definition: lock.h:518
#define lengthof(array)
Definition: c.h:734
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1805
#define ERROR
Definition: elog.h:46
unsigned int uint32
Definition: c.h:441
Definition: lock.h:299
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:516
uint16 LOCKMETHODID
Definition: lock.h:126
#define Assert(condition)
Definition: c.h:804
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1203
uint8 locktag_lockmethodid
Definition: lock.h:173
#define elog(elevel,...)
Definition: elog.h:232
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

Definition at line 1798 of file lock.c.

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

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

1799 {
1800  Assert(locallock->nLocks > 0);
1801  locallock->lockCleared = true;
1802 }
#define Assert(condition)
Definition: c.h:804
int64 nLocks
Definition: lock.h:426
bool lockCleared
Definition: lock.h:431

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

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

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