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

Go to the source code of this file.

Data Structures

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

Macros

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

Typedefs

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

Enumerations

enum  LockTagType {
  LOCKTAG_RELATION, LOCKTAG_RELATION_EXTEND, LOCKTAG_PAGE, LOCKTAG_TUPLE,
  LOCKTAG_TRANSACTION, LOCKTAG_VIRTUALTRANSACTION, LOCKTAG_SPECULATIVE_TOKEN, LOCKTAG_OBJECT,
  LOCKTAG_USERLOCK, LOCKTAG_ADVISORY
}
 
enum  LockAcquireResult { LOCKACQUIRE_NOT_AVAIL, LOCKACQUIRE_OK, LOCKACQUIRE_ALREADY_HELD }
 
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 report_memory_error)
 
void AbortStrongLockAcquire (void)
 
bool LockRelease (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
void LockReleaseAll (LOCKMETHODID lockmethodid, bool allLocks)
 
void LockReleaseSession (LOCKMETHODID lockmethodid)
 
void LockReleaseCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
void LockReassignCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
bool LockHasWaiters (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
VirtualTransactionIdGetLockConflicts (const LOCKTAG *locktag, LOCKMODE lockmode)
 
void AtPrepare_Locks (void)
 
void PostPrepare_Locks (TransactionId xid)
 
int LockCheckConflicts (LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
 
void GrantLock (LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
 
void GrantAwaitedLock (void)
 
void RemoveFromWaitQueue (PGPROC *proc, uint32 hashcode)
 
Size LockShmemSize (void)
 
LockDataGetLockStatusData (void)
 
BlockedProcsDataGetBlockerStatusData (int blocked_pid)
 
xl_standby_lockGetRunningTransactionLocks (int *nlocks)
 
const char * GetLockmodeName (LOCKMETHODID lockmethodid, LOCKMODE mode)
 
void lock_twophase_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_postcommit (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_postabort (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_standby_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
DeadLockState DeadLockCheck (PGPROC *proc)
 
PGPROCGetBlockingAutoVacuumPgproc (void)
 
void DeadLockReport (void) pg_attribute_noreturn()
 
void RememberSimpleDeadLock (PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
 
void InitDeadLockChecking (void)
 
int LockWaiterCount (const LOCKTAG *locktag)
 
void VirtualXactLockTableInsert (VirtualTransactionId vxid)
 
void VirtualXactLockTableCleanup (void)
 
bool VirtualXactLock (VirtualTransactionId vxid, bool wait)
 

Variables

int max_locks_per_xact
 
const char *const LockTagTypeNames []
 

Macro Definition Documentation

◆ DEFAULT_LOCKMETHOD

#define DEFAULT_LOCKMETHOD   1

◆ GET_VXID_FROM_PGPROC

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

Definition at line 80 of file lock.h.

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

◆ InvalidLocalTransactionId

◆ LOCALLOCK_LOCKMETHOD

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

Definition at line 417 of file lock.h.

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

◆ LocalTransactionIdIsValid

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

Definition at line 70 of file lock.h.

Referenced by GetNextLocalTransactionId(), and VirtualXactLockTableCleanup().

◆ LOCK_LOCKMETHOD

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

Definition at line 300 of file lock.h.

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

◆ LOCKBIT_OFF

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

Definition at line 88 of file lock.h.

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

◆ LOCKBIT_ON

◆ LockHashPartition

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

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

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

◆ LOCKTAG_LAST_TYPE

#define LOCKTAG_LAST_TYPE   LOCKTAG_ADVISORY

Definition at line 166 of file lock.h.

Referenced by GetLockNameFromTagType(), and pg_lock_status().

◆ MAX_LOCKMODES

◆ PROCLOCK_LOCKMETHOD

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

Definition at line 357 of file lock.h.

◆ SET_LOCKTAG_ADVISORY

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

Definition at line 257 of file lock.h.

◆ SET_LOCKTAG_OBJECT

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

Definition at line 249 of file lock.h.

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

◆ SET_LOCKTAG_PAGE

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

Definition at line 209 of file lock.h.

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

◆ SET_LOCKTAG_RELATION

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

Definition at line 193 of file lock.h.

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

◆ SET_LOCKTAG_RELATION_EXTEND

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

Definition at line 201 of file lock.h.

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

◆ SET_LOCKTAG_SPECULATIVE_INSERTION

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

Definition at line 241 of file lock.h.

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

◆ SET_LOCKTAG_TRANSACTION

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

Definition at line 225 of file lock.h.

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

◆ SET_LOCKTAG_TUPLE

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

Definition at line 217 of file lock.h.

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

◆ SET_LOCKTAG_VIRTUALTRANSACTION

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

Definition at line 233 of file lock.h.

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

◆ SetInvalidVirtualTransactionId

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

Definition at line 77 of file lock.h.

Referenced by DefineIndex(), and InitPredicateLocks().

◆ USER_LOCKMETHOD

#define USER_LOCKMETHOD   2

Definition at line 129 of file lock.h.

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

◆ VirtualTransactionIdEquals

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

Definition at line 74 of file lock.h.

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

◆ VirtualTransactionIdIsValid

#define VirtualTransactionIdIsValid (   vxid)

Typedef Documentation

◆ BlockedProcData

◆ BlockedProcsData

◆ LOCALLOCK

◆ LOCALLOCKOWNER

◆ LOCALLOCKTAG

◆ LOCK

typedef struct LOCK LOCK

◆ LockData

◆ LockInstanceData

◆ LockMethod

Definition at line 119 of file lock.h.

◆ LockMethodData

◆ LOCKMETHODID

Definition at line 125 of file lock.h.

◆ LOCKTAG

◆ LockTagType

◆ PGPROC

Definition at line 28 of file lock.h.

◆ PROC_QUEUE

◆ PROCLOCK

◆ PROCLOCKTAG

Enumeration Type Documentation

◆ DeadLockState

Enumerator
DS_NOT_YET_CHECKED 
DS_NO_DEADLOCK 
DS_SOFT_DEADLOCK 
DS_HARD_DEADLOCK 
DS_BLOCKED_BY_AUTOVACUUM 

Definition at line 479 of file lock.h.

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

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 

Definition at line 471 of file lock.h.

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

◆ LockTagType

Enumerator
LOCKTAG_RELATION 
LOCKTAG_RELATION_EXTEND 
LOCKTAG_PAGE 
LOCKTAG_TUPLE 
LOCKTAG_TRANSACTION 
LOCKTAG_VIRTUALTRANSACTION 
LOCKTAG_SPECULATIVE_TOKEN 
LOCKTAG_OBJECT 
LOCKTAG_USERLOCK 
LOCKTAG_ADVISORY 

Definition at line 138 of file lock.h.

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

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )

Definition at line 1614 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

1615 {
1616  uint32 fasthashcode;
1617  LOCALLOCK *locallock = StrongLockInProgress;
1618 
1619  if (locallock == NULL)
1620  return;
1621 
1622  fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1623  Assert(locallock->holdsStrongLockCount == true);
1625  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1626  FastPathStrongRelationLocks->count[fasthashcode]--;
1627  locallock->holdsStrongLockCount = false;
1628  StrongLockInProgress = NULL;
1630 }
uint32 hashcode
Definition: lock.h:409
bool holdsStrongLockCount
Definition: lock.h:413
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:259
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
unsigned int uint32
Definition: c.h:296
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:670

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

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

3060 {
3062  LOCALLOCK *locallock;
3063 
3064  /*
3065  * For the most part, we don't need to touch shared memory for this ---
3066  * all the necessary state information is in the locallock table.
3067  * Fast-path locks are an exception, however: we move any such locks to
3068  * the main table before allowing PREPARE TRANSACTION to succeed.
3069  */
3071 
3072  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3073  {
3074  TwoPhaseLockRecord record;
3075  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3076  bool haveSessionLock;
3077  bool haveXactLock;
3078  int i;
3079 
3080  /*
3081  * Ignore VXID locks. We don't want those to be held by prepared
3082  * transactions, since they aren't meaningful after a restart.
3083  */
3084  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3085  continue;
3086 
3087  /* Ignore it if we don't actually hold the lock */
3088  if (locallock->nLocks <= 0)
3089  continue;
3090 
3091  /* Scan to see whether we hold it at session or transaction level */
3092  haveSessionLock = haveXactLock = false;
3093  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3094  {
3095  if (lockOwners[i].owner == NULL)
3096  haveSessionLock = true;
3097  else
3098  haveXactLock = true;
3099  }
3100 
3101  /* Ignore it if we have only session lock */
3102  if (!haveXactLock)
3103  continue;
3104 
3105  /*
3106  * If we have both session- and transaction-level locks, fail. This
3107  * should never happen with regular locks, since we only take those at
3108  * session level in some special operations like VACUUM. It's
3109  * possible to hit this with advisory locks, though.
3110  *
3111  * It would be nice if we could keep the session hold and give away
3112  * the transactional hold to the prepared xact. However, that would
3113  * require two PROCLOCK objects, and we cannot be sure that another
3114  * PROCLOCK will be available when it comes time for PostPrepare_Locks
3115  * to do the deed. So for now, we error out while we can still do so
3116  * safely.
3117  */
3118  if (haveSessionLock)
3119  ereport(ERROR,
3120  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3121  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3122 
3123  /*
3124  * If the local lock was taken via the fast-path, we need to move it
3125  * to the primary lock table, or just get a pointer to the existing
3126  * primary lock table entry if by chance it's already been
3127  * transferred.
3128  */
3129  if (locallock->proclock == NULL)
3130  {
3131  locallock->proclock = FastPathGetRelationLockEntry(locallock);
3132  locallock->lock = locallock->proclock->tag.myLock;
3133  }
3134 
3135  /*
3136  * Arrange to not release any strong lock count held by this lock
3137  * entry. We must retain the count until the prepared transaction is
3138  * committed or rolled back.
3139  */
3140  locallock->holdsStrongLockCount = false;
3141 
3142  /*
3143  * Create a 2PC record.
3144  */
3145  memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3146  record.lockmode = locallock->tag.mode;
3147 
3149  &record, sizeof(TwoPhaseLockRecord));
3150  }
3151 }
PROCLOCKTAG tag
Definition: lock.h:347
LOCALLOCKTAG tag
Definition: lock.h:404
static HTAB * LockMethodLocalHash
Definition: lock.c:255
bool holdsStrongLockCount
Definition: lock.h:413
int numLockOwners
Definition: lock.h:411
LOCKTAG lock
Definition: lock.h:385
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition: lock.c:2644
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
Definition: lock.h:178
int errcode(int sqlerrcode)
Definition: elog.c:575
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1164
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:122
uint8 locktag_type
Definition: lock.h:184
#define TWOPHASE_RM_LOCK_ID
Definition: twophase_rmgr.h:25
LOCALLOCKOWNER * lockOwners
Definition: lock.h:414
LOCK * lock
Definition: lock.h:407
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
int64 nLocks
Definition: lock.h:410
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
LOCK * myLock
Definition: lock.h:340
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
LOCKMODE lockmode
Definition: lock.c:161

◆ DeadLockCheck()

DeadLockState DeadLockCheck ( PGPROC proc)

Definition at line 217 of file deadlock.c.

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

Referenced by CheckDeadLock().

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

◆ DeadLockReport()

void DeadLockReport ( void  )

Definition at line 1077 of file deadlock.c.

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

Referenced by WaitOnLock().

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

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 556 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

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

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

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

3583 {
3584  BlockedProcsData *data;
3585  PGPROC *proc;
3586  int i;
3587 
3588  data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
3589 
3590  /*
3591  * Guess how much space we'll need, and preallocate. Most of the time
3592  * this will avoid needing to do repalloc while holding the LWLocks. (We
3593  * assume, but check with an Assert, that MaxBackends is enough entries
3594  * for the procs[] array; the other two could need enlargement, though.)
3595  */
3596  data->nprocs = data->nlocks = data->npids = 0;
3597  data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3598  data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
3599  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3600  data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3601 
3602  /*
3603  * In order to search the ProcArray for blocked_pid and assume that that
3604  * entry won't immediately disappear under us, we must hold ProcArrayLock.
3605  * In addition, to examine the lock grouping fields of any other backend,
3606  * we must hold all the hash partition locks. (Only one of those locks is
3607  * actually relevant for any one lock group, but we can't know which one
3608  * ahead of time.) It's fairly annoying to hold all those locks
3609  * throughout this, but it's no worse than GetLockStatusData(), and it
3610  * does have the advantage that we're guaranteed to return a
3611  * self-consistent instantaneous state.
3612  */
3613  LWLockAcquire(ProcArrayLock, LW_SHARED);
3614 
3615  proc = BackendPidGetProcWithLock(blocked_pid);
3616 
3617  /* Nothing to do if it's gone */
3618  if (proc != NULL)
3619  {
3620  /*
3621  * Acquire lock on the entire shared lock data structure. See notes
3622  * in GetLockStatusData().
3623  */
3624  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3626 
3627  if (proc->lockGroupLeader == NULL)
3628  {
3629  /* Easy case, proc is not a lock group member */
3630  GetSingleProcBlockerStatusData(proc, data);
3631  }
3632  else
3633  {
3634  /* Examine all procs in proc's lock group */
3635  dlist_iter iter;
3636 
3638  {
3639  PGPROC *memberProc;
3640 
3641  memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
3642  GetSingleProcBlockerStatusData(memberProc, data);
3643  }
3644  }
3645 
3646  /*
3647  * And release locks. See notes in GetLockStatusData().
3648  */
3649  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3651 
3652  Assert(data->nprocs <= data->maxprocs);
3653  }
3654 
3655  LWLockRelease(ProcArrayLock);
3656 
3657  return data;
3658 }
int * waiter_pids
Definition: lock.h:460
dlist_head lockGroupMembers
Definition: proc.h:201
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
BlockedProcData * procs
Definition: lock.h:458
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2369
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition: lock.c:3662
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:500
int MaxBackends
Definition: globals.c:126
int maxlocks
Definition: lock.h:464
LockInstanceData * locks
Definition: lock.h:459
dlist_node * cur
Definition: ilist.h:161
#define Assert(condition)
Definition: c.h:670
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void * palloc(Size size)
Definition: mcxt.c:848
int i
Definition: proc.h:95
PGPROC * lockGroupLeader
Definition: proc.h:200
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
int maxprocs
Definition: lock.h:462

◆ GetBlockingAutoVacuumPgproc()

PGPROC* GetBlockingAutoVacuumPgproc ( void  )

Definition at line 293 of file deadlock.c.

References blocking_autovacuum_proc.

Referenced by ProcSleep().

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

◆ GetLockConflicts()

VirtualTransactionId* GetLockConflicts ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 2745 of file lock.c.

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

Referenced by ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

2746 {
2747  static VirtualTransactionId *vxids;
2748  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
2749  LockMethod lockMethodTable;
2750  LOCK *lock;
2751  LOCKMASK conflictMask;
2752  SHM_QUEUE *procLocks;
2753  PROCLOCK *proclock;
2754  uint32 hashcode;
2755  LWLock *partitionLock;
2756  int count = 0;
2757  int fast_count = 0;
2758 
2759  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2760  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2761  lockMethodTable = LockMethods[lockmethodid];
2762  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2763  elog(ERROR, "unrecognized lock mode: %d", lockmode);
2764 
2765  /*
2766  * Allocate memory to store results, and fill with InvalidVXID. We only
2767  * need enough space for MaxBackends + a terminator, since prepared xacts
2768  * don't count. InHotStandby allocate once in TopMemoryContext.
2769  */
2770  if (InHotStandby)
2771  {
2772  if (vxids == NULL)
2773  vxids = (VirtualTransactionId *)
2775  sizeof(VirtualTransactionId) * (MaxBackends + 1));
2776  }
2777  else
2778  vxids = (VirtualTransactionId *)
2779  palloc0(sizeof(VirtualTransactionId) * (MaxBackends + 1));
2780 
2781  /* Compute hash code and partition lock, and look up conflicting modes. */
2782  hashcode = LockTagHashCode(locktag);
2783  partitionLock = LockHashPartitionLock(hashcode);
2784  conflictMask = lockMethodTable->conflictTab[lockmode];
2785 
2786  /*
2787  * Fast path locks might not have been entered in the primary lock table.
2788  * If the lock we're dealing with could conflict with such a lock, we must
2789  * examine each backend's fast-path array for conflicts.
2790  */
2791  if (ConflictsWithRelationFastPath(locktag, lockmode))
2792  {
2793  int i;
2794  Oid relid = locktag->locktag_field2;
2795  VirtualTransactionId vxid;
2796 
2797  /*
2798  * Iterate over relevant PGPROCs. Anything held by a prepared
2799  * transaction will have been transferred to the primary lock table,
2800  * so we need not worry about those. This is all a bit fuzzy, because
2801  * new locks could be taken after we've visited a particular
2802  * partition, but the callers had better be prepared to deal with that
2803  * anyway, since the locks could equally well be taken between the
2804  * time we return the value and the time the caller does something
2805  * with it.
2806  */
2807  for (i = 0; i < ProcGlobal->allProcCount; i++)
2808  {
2809  PGPROC *proc = &ProcGlobal->allProcs[i];
2810  uint32 f;
2811 
2812  /* A backend never blocks itself */
2813  if (proc == MyProc)
2814  continue;
2815 
2817 
2818  /*
2819  * If the target backend isn't referencing the same database as
2820  * the lock, then we needn't examine the individual relation IDs
2821  * at all; none of them can be relevant.
2822  *
2823  * See FastPathTransferLocks() for discussion of why we do this
2824  * test after acquiring the lock.
2825  */
2826  if (proc->databaseId != locktag->locktag_field1)
2827  {
2828  LWLockRelease(&proc->backendLock);
2829  continue;
2830  }
2831 
2832  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2833  {
2834  uint32 lockmask;
2835 
2836  /* Look for an allocated slot matching the given relid. */
2837  if (relid != proc->fpRelId[f])
2838  continue;
2839  lockmask = FAST_PATH_GET_BITS(proc, f);
2840  if (!lockmask)
2841  continue;
2842  lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
2843 
2844  /*
2845  * There can only be one entry per relation, so if we found it
2846  * and it doesn't conflict, we can skip the rest of the slots.
2847  */
2848  if ((lockmask & conflictMask) == 0)
2849  break;
2850 
2851  /* Conflict! */
2852  GET_VXID_FROM_PGPROC(vxid, *proc);
2853 
2854  /*
2855  * If we see an invalid VXID, then either the xact has already
2856  * committed (or aborted), or it's a prepared xact. In either
2857  * case we may ignore it.
2858  */
2859  if (VirtualTransactionIdIsValid(vxid))
2860  vxids[count++] = vxid;
2861 
2862  /* No need to examine remaining slots. */
2863  break;
2864  }
2865 
2866  LWLockRelease(&proc->backendLock);
2867  }
2868  }
2869 
2870  /* Remember how many fast-path conflicts we found. */
2871  fast_count = count;
2872 
2873  /*
2874  * Look up the lock object matching the tag.
2875  */
2876  LWLockAcquire(partitionLock, LW_SHARED);
2877 
2879  (const void *) locktag,
2880  hashcode,
2881  HASH_FIND,
2882  NULL);
2883  if (!lock)
2884  {
2885  /*
2886  * If the lock object doesn't exist, there is nothing holding a lock
2887  * on this lockable object.
2888  */
2889  LWLockRelease(partitionLock);
2890  vxids[count].backendId = InvalidBackendId;
2892  return vxids;
2893  }
2894 
2895  /*
2896  * Examine each existing holder (or awaiter) of the lock.
2897  */
2898 
2899  procLocks = &(lock->procLocks);
2900 
2901  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2902  offsetof(PROCLOCK, lockLink));
2903 
2904  while (proclock)
2905  {
2906  if (conflictMask & proclock->holdMask)
2907  {
2908  PGPROC *proc = proclock->tag.myProc;
2909 
2910  /* A backend never blocks itself */
2911  if (proc != MyProc)
2912  {
2913  VirtualTransactionId vxid;
2914 
2915  GET_VXID_FROM_PGPROC(vxid, *proc);
2916 
2917  /*
2918  * If we see an invalid VXID, then either the xact has already
2919  * committed (or aborted), or it's a prepared xact. In either
2920  * case we may ignore it.
2921  */
2922  if (VirtualTransactionIdIsValid(vxid))
2923  {
2924  int i;
2925 
2926  /* Avoid duplicate entries. */
2927  for (i = 0; i < fast_count; ++i)
2928  if (VirtualTransactionIdEquals(vxids[i], vxid))
2929  break;
2930  if (i >= fast_count)
2931  vxids[count++] = vxid;
2932  }
2933  }
2934  }
2935 
2936  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
2937  offsetof(PROCLOCK, lockLink));
2938  }
2939 
2940  LWLockRelease(partitionLock);
2941 
2942  if (count > MaxBackends) /* should never happen */
2943  elog(PANIC, "too many conflicting locks found");
2944 
2945  vxids[count].backendId = InvalidBackendId;
2947  return vxids;
2948 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
PROCLOCKTAG tag
Definition: lock.h:347
Definition: lwlock.h:32
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:80
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
const LOCKMASK * conflictTab
Definition: lock.h:114
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
SHM_QUEUE lockLink
Definition: lock.h:353
#define InHotStandby
Definition: xlog.h:74
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define lengthof(array)
Definition: c.h:600
unsigned int Oid
Definition: postgres_ext.h:31
LocalTransactionId localTransactionId
Definition: lock.h:66
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:74
#define ERROR
Definition: elog.h:43
int MaxBackends
Definition: globals.c:126
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
uint32 locktag_field2
Definition: lock.h:181
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:296
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
MemoryContext TopMemoryContext
Definition: mcxt.c:43
uint16 LOCKMETHODID
Definition: lock.h:125
SHM_QUEUE procLocks
Definition: lock.h:292
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:71
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:877
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:191
BackendId backendId
Definition: lock.h:65
LWLock backendLock
Definition: proc.h:187
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
uint32 allProcCount
Definition: proc.h:248
int LOCKMASK
Definition: lockdefs.h:25
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
Definition: lock.h:344
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:706
#define InvalidLocalTransactionId
Definition: lock.h:69
int i
PGPROC * allProcs
Definition: proc.h:244
static const LockMethod LockMethods[]
Definition: lock.c:150
#define elog
Definition: elog.h:219
uint32 locktag_field1
Definition: lock.h:180
Definition: proc.h:95
#define offsetof(type, field)
Definition: c.h:593
int numLockModes
Definition: lock.h:113

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

Definition at line 3845 of file lock.c.

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

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

3846 {
3847  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
3848  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
3849  return LockMethods[lockmethodid]->lockModeNames[mode];
3850 }
#define lengthof(array)
Definition: c.h:600
#define Assert(condition)
Definition: c.h:670
static const LockMethod LockMethods[]
Definition: lock.c:150
const char *const * lockModeNames
Definition: lock.h:115

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)

Definition at line 460 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

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

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

Definition at line 3398 of file lock.c.

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

Referenced by pg_lock_status().

3399 {
3400  LockData *data;
3401  PROCLOCK *proclock;
3402  HASH_SEQ_STATUS seqstat;
3403  int els;
3404  int el;
3405  int i;
3406 
3407  data = (LockData *) palloc(sizeof(LockData));
3408 
3409  /* Guess how much space we'll need. */
3410  els = MaxBackends;
3411  el = 0;
3412  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3413 
3414  /*
3415  * First, we iterate through the per-backend fast-path arrays, locking
3416  * them one at a time. This might produce an inconsistent picture of the
3417  * system state, but taking all of those LWLocks at the same time seems
3418  * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3419  * matter too much, because none of these locks can be involved in lock
3420  * conflicts anyway - anything that might must be present in the main lock
3421  * table. (For the same reason, we don't sweat about making leaderPid
3422  * completely valid. We cannot safely dereference another backend's
3423  * lockGroupLeader field without holding all lock partition locks, and
3424  * it's not worth that.)
3425  */
3426  for (i = 0; i < ProcGlobal->allProcCount; ++i)
3427  {
3428  PGPROC *proc = &ProcGlobal->allProcs[i];
3429  uint32 f;
3430 
3432 
3433  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
3434  {
3435  LockInstanceData *instance;
3436  uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3437 
3438  /* Skip unallocated slots. */
3439  if (!lockbits)
3440  continue;
3441 
3442  if (el >= els)
3443  {
3444  els += MaxBackends;
3445  data->locks = (LockInstanceData *)
3446  repalloc(data->locks, sizeof(LockInstanceData) * els);
3447  }
3448 
3449  instance = &data->locks[el];
3450  SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3451  proc->fpRelId[f]);
3452  instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3453  instance->waitLockMode = NoLock;
3454  instance->backend = proc->backendId;
3455  instance->lxid = proc->lxid;
3456  instance->pid = proc->pid;
3457  instance->leaderPid = proc->pid;
3458  instance->fastpath = true;
3459 
3460  el++;
3461  }
3462 
3463  if (proc->fpVXIDLock)
3464  {
3465  VirtualTransactionId vxid;
3466  LockInstanceData *instance;
3467 
3468  if (el >= els)
3469  {
3470  els += MaxBackends;
3471  data->locks = (LockInstanceData *)
3472  repalloc(data->locks, sizeof(LockInstanceData) * els);
3473  }
3474 
3475  vxid.backendId = proc->backendId;
3477 
3478  instance = &data->locks[el];
3479  SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3480  instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3481  instance->waitLockMode = NoLock;
3482  instance->backend = proc->backendId;
3483  instance->lxid = proc->lxid;
3484  instance->pid = proc->pid;
3485  instance->leaderPid = proc->pid;
3486  instance->fastpath = true;
3487 
3488  el++;
3489  }
3490 
3491  LWLockRelease(&proc->backendLock);
3492  }
3493 
3494  /*
3495  * Next, acquire lock on the entire shared lock data structure. We do
3496  * this so that, at least for locks in the primary lock table, the state
3497  * will be self-consistent.
3498  *
3499  * Since this is a read-only operation, we take shared instead of
3500  * exclusive lock. There's not a whole lot of point to this, because all
3501  * the normal operations require exclusive lock, but it doesn't hurt
3502  * anything either. It will at least allow two backends to do
3503  * GetLockStatusData in parallel.
3504  *
3505  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3506  */
3507  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3509 
3510  /* Now we can safely count the number of proclocks */
3512  if (data->nelements > els)
3513  {
3514  els = data->nelements;
3515  data->locks = (LockInstanceData *)
3516  repalloc(data->locks, sizeof(LockInstanceData) * els);
3517  }
3518 
3519  /* Now scan the tables to copy the data */
3521 
3522  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3523  {
3524  PGPROC *proc = proclock->tag.myProc;
3525  LOCK *lock = proclock->tag.myLock;
3526  LockInstanceData *instance = &data->locks[el];
3527 
3528  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3529  instance->holdMask = proclock->holdMask;
3530  if (proc->waitLock == proclock->tag.myLock)
3531  instance->waitLockMode = proc->waitLockMode;
3532  else
3533  instance->waitLockMode = NoLock;
3534  instance->backend = proc->backendId;
3535  instance->lxid = proc->lxid;
3536  instance->pid = proc->pid;
3537  instance->leaderPid = proclock->groupLeader->pid;
3538  instance->fastpath = false;
3539 
3540  el++;
3541  }
3542 
3543  /*
3544  * And release locks. We do this in reverse order for two reasons: (1)
3545  * Anyone else who needs more than one of the locks will be trying to lock
3546  * them in increasing order; we don't want to release the other process
3547  * until it can get all the locks it needs. (2) This avoids O(N^2)
3548  * behavior inside LWLockRelease.
3549  */
3550  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3552 
3553  Assert(el == data->nelements);
3554 
3555  return data;
3556 }
PROCLOCKTAG tag
Definition: lock.h:347
LockInstanceData * locks
Definition: lock.h:440
BackendId backendId
Definition: proc.h:113
#define ExclusiveLock
Definition: lockdefs.h:44
LOCKMASK holdMask
Definition: lock.h:351
bool fastpath
Definition: lock.h:434
LOCKMODE waitLockMode
Definition: proc.h:138
LOCKTAG tag
Definition: lock.h:287
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
Definition: lock.h:178
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1331
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
bool fpVXIDLock
Definition: proc.h:192
Definition: lock.h:437
LocalTransactionId localTransactionId
Definition: lock.h:66
LOCKTAG locktag
Definition: lock.h:427
LOCKMODE waitLockMode
Definition: lock.h:429
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
int leaderPid
Definition: lock.h:433
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:500
int MaxBackends
Definition: globals.c:126
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:193
#define NoLock
Definition: lockdefs.h:34
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:296
Definition: lock.h:284
LOCK * waitLock
Definition: proc.h:136
int nelements
Definition: lock.h:439
BackendId backend
Definition: lock.h:430
LocalTransactionId lxid
Definition: lock.h:431
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:191
#define Assert(condition)
Definition: c.h:670
BackendId backendId
Definition: lock.h:65
LWLock backendLock
Definition: proc.h:187
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition: lock.h:233
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
uint32 allProcCount
Definition: proc.h:248
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:962
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
LOCKMASK holdMask
Definition: lock.h:428
PGPROC * myProc
Definition: lock.h:341
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
void * palloc(Size size)
Definition: mcxt.c:848
int i
LOCK * myLock
Definition: lock.h:340
PGPROC * allProcs
Definition: proc.h:244
Definition: proc.h:95
int pid
Definition: proc.h:109
LocalTransactionId fpLocalTransactionId
Definition: proc.h:193
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
PGPROC * groupLeader
Definition: lock.h:350
LocalTransactionId lxid
Definition: proc.h:106

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 472 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

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

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

Definition at line 3762 of file lock.c.

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

Referenced by LogStandbySnapshot().

3763 {
3764  xl_standby_lock *accessExclusiveLocks;
3765  PROCLOCK *proclock;
3766  HASH_SEQ_STATUS seqstat;
3767  int i;
3768  int index;
3769  int els;
3770 
3771  /*
3772  * Acquire lock on the entire shared lock data structure.
3773  *
3774  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3775  */
3776  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3778 
3779  /* Now we can safely count the number of proclocks */
3781 
3782  /*
3783  * Allocating enough space for all locks in the lock table is overkill,
3784  * but it's more convenient and faster than having to enlarge the array.
3785  */
3786  accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
3787 
3788  /* Now scan the tables to copy the data */
3790 
3791  /*
3792  * If lock is a currently granted AccessExclusiveLock then it will have
3793  * just one proclock holder, so locks are never accessed twice in this
3794  * particular case. Don't copy this code for use elsewhere because in the
3795  * general case this will give you duplicate locks when looking at
3796  * non-exclusive lock types.
3797  */
3798  index = 0;
3799  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3800  {
3801  /* make sure this definition matches the one used in LockAcquire */
3802  if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
3803  proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION)
3804  {
3805  PGPROC *proc = proclock->tag.myProc;
3806  PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno];
3807  LOCK *lock = proclock->tag.myLock;
3808  TransactionId xid = pgxact->xid;
3809 
3810  /*
3811  * Don't record locks for transactions if we know they have
3812  * already issued their WAL record for commit but not yet released
3813  * lock. It is still possible that we see locks held by already
3814  * complete transactions, if they haven't yet zeroed their xids.
3815  */
3816  if (!TransactionIdIsValid(xid))
3817  continue;
3818 
3819  accessExclusiveLocks[index].xid = xid;
3820  accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
3821  accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
3822 
3823  index++;
3824  }
3825  }
3826 
3827  Assert(index <= els);
3828 
3829  /*
3830  * And release locks. We do this in reverse order for two reasons: (1)
3831  * Anyone else who needs more than one of the locks will be trying to lock
3832  * them in increasing order; we don't want to release the other process
3833  * until it can get all the locks it needs. (2) This avoids O(N^2)
3834  * behavior inside LWLockRelease.
3835  */
3836  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3838 
3839  *nlocks = index;
3840  return accessExclusiveLocks;
3841 }
PROCLOCKTAG tag
Definition: lock.h:347
uint32 TransactionId
Definition: c.h:445
Definition: proc.h:219
PGXACT * allPgXact
Definition: proc.h:246
LOCKMASK holdMask
Definition: lock.h:351
TransactionId xid
Definition: proc.h:221
LOCKTAG tag
Definition: lock.h:287
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1331
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:500
uint32 locktag_field2
Definition: lock.h:181
Definition: lock.h:284
TransactionId xid
Definition: lockdefs.h:50
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:670
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: lock.h:344
int pgprocno
Definition: proc.h:110
void * palloc(Size size)
Definition: mcxt.c:848
int i
LOCK * myLock
Definition: lock.h:340
#define TransactionIdIsValid(xid)
Definition: transam.h:41
uint32 locktag_field1
Definition: lock.h:180
Definition: proc.h:95
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1643 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

1644 {
1646 }
static LOCALLOCK * awaitedLock
Definition: lock.c:260
static ResourceOwner awaitedOwner
Definition: lock.c:261
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1549

◆ GrantLock()

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

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

1416 {
1417  lock->nGranted++;
1418  lock->granted[lockmode]++;
1419  lock->grantMask |= LOCKBIT_ON(lockmode);
1420  if (lock->granted[lockmode] == lock->requested[lockmode])
1421  lock->waitMask &= LOCKBIT_OFF(lockmode);
1422  proclock->holdMask |= LOCKBIT_ON(lockmode);
1423  LOCK_PRINT("GrantLock", lock, lockmode);
1424  Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1425  Assert(lock->nGranted <= lock->nRequested);
1426 }
int nRequested
Definition: lock.h:295
LOCKMASK holdMask
Definition: lock.h:351
int nGranted
Definition: lock.h:297
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:88
int granted[MAX_LOCKMODES]
Definition: lock.h:296
LOCKMASK waitMask
Definition: lock.h:291
int requested[MAX_LOCKMODES]
Definition: lock.h:294
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:670
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290

◆ InitDeadLockChecking()

void InitDeadLockChecking ( void  )

Definition at line 143 of file deadlock.c.

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

Referenced by InitProcess().

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

◆ InitLocks()

void InitLocks ( void  )

Definition at line 377 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ lock_twophase_postabort()

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

Definition at line 4197 of file lock.c.

References lock_twophase_postcommit().

4199 {
4200  lock_twophase_postcommit(xid, info, recdata, len);
4201 }
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
Definition: lock.c:4171

◆ lock_twophase_postcommit()

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

Definition at line 4171 of file lock.c.

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

Referenced by lock_twophase_postabort().

4173 {
4174  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4175  PGPROC *proc = TwoPhaseGetDummyProc(xid);
4176  LOCKTAG *locktag;
4177  LOCKMETHODID lockmethodid;
4178  LockMethod lockMethodTable;
4179 
4180  Assert(len == sizeof(TwoPhaseLockRecord));
4181  locktag = &rec->locktag;
4182  lockmethodid = locktag->locktag_lockmethodid;
4183 
4184  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4185  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4186  lockMethodTable = LockMethods[lockmethodid];
4187 
4188  LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4189 }
PGPROC * TwoPhaseGetDummyProc(TransactionId xid)
Definition: twophase.c:868
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:2962
Definition: lock.h:178
#define lengthof(array)
Definition: c.h:600
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:670
uint8 locktag_lockmethodid
Definition: lock.h:185
static const LockMethod LockMethods[]
Definition: lock.c:150
#define elog
Definition: elog.h:219
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:95

◆ lock_twophase_recover()

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

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

3960 {
3961  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
3962  PGPROC *proc = TwoPhaseGetDummyProc(xid);
3963  LOCKTAG *locktag;
3964  LOCKMODE lockmode;
3965  LOCKMETHODID lockmethodid;
3966  LOCK *lock;
3967  PROCLOCK *proclock;
3968  PROCLOCKTAG proclocktag;
3969  bool found;
3970  uint32 hashcode;
3971  uint32 proclock_hashcode;
3972  int partition;
3973  LWLock *partitionLock;
3974  LockMethod lockMethodTable;
3975 
3976  Assert(len == sizeof(TwoPhaseLockRecord));
3977  locktag = &rec->locktag;
3978  lockmode = rec->lockmode;
3979  lockmethodid = locktag->locktag_lockmethodid;
3980 
3981  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
3982  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
3983  lockMethodTable = LockMethods[lockmethodid];
3984 
3985  hashcode = LockTagHashCode(locktag);
3986  partition = LockHashPartition(hashcode);
3987  partitionLock = LockHashPartitionLock(hashcode);
3988 
3989  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3990 
3991  /*
3992  * Find or create a lock with this tag.
3993  */
3995  (void *) locktag,
3996  hashcode,
3998  &found);
3999  if (!lock)
4000  {
4001  LWLockRelease(partitionLock);
4002  ereport(ERROR,
4003  (errcode(ERRCODE_OUT_OF_MEMORY),
4004  errmsg("out of shared memory"),
4005  errhint("You might need to increase max_locks_per_transaction.")));
4006  }
4007 
4008  /*
4009  * if it's a new lock object, initialize it
4010  */
4011  if (!found)
4012  {
4013  lock->grantMask = 0;
4014  lock->waitMask = 0;
4015  SHMQueueInit(&(lock->procLocks));
4016  ProcQueueInit(&(lock->waitProcs));
4017  lock->nRequested = 0;
4018  lock->nGranted = 0;
4019  MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4020  MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4021  LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4022  }
4023  else
4024  {
4025  LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4026  Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4027  Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4028  Assert(lock->nGranted <= lock->nRequested);
4029  }
4030 
4031  /*
4032  * Create the hash key for the proclock table.
4033  */
4034  proclocktag.myLock = lock;
4035  proclocktag.myProc = proc;
4036 
4037  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4038 
4039  /*
4040  * Find or create a proclock entry with this tag
4041  */
4043  (void *) &proclocktag,
4044  proclock_hashcode,
4046  &found);
4047  if (!proclock)
4048  {
4049  /* Oops, not enough shmem for the proclock */
4050  if (lock->nRequested == 0)
4051  {
4052  /*
4053  * There are no other requestors of this lock, so garbage-collect
4054  * the lock object. We *must* do this to avoid a permanent leak
4055  * of shared memory, because there won't be anything to cause
4056  * anyone to release the lock object later.
4057  */
4058  Assert(SHMQueueEmpty(&(lock->procLocks)));
4060  (void *) &(lock->tag),
4061  hashcode,
4062  HASH_REMOVE,
4063  NULL))
4064  elog(PANIC, "lock table corrupted");
4065  }
4066  LWLockRelease(partitionLock);
4067  ereport(ERROR,
4068  (errcode(ERRCODE_OUT_OF_MEMORY),
4069  errmsg("out of shared memory"),
4070  errhint("You might need to increase max_locks_per_transaction.")));
4071  }
4072 
4073  /*
4074  * If new, initialize the new entry
4075  */
4076  if (!found)
4077  {
4078  Assert(proc->lockGroupLeader == NULL);
4079  proclock->groupLeader = proc;
4080  proclock->holdMask = 0;
4081  proclock->releaseMask = 0;
4082  /* Add proclock to appropriate lists */
4083  SHMQueueInsertBefore(&lock->procLocks, &proclock->lockLink);
4084  SHMQueueInsertBefore(&(proc->myProcLocks[partition]),
4085  &proclock->procLink);
4086  PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4087  }
4088  else
4089  {
4090  PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4091  Assert((proclock->holdMask & ~lock->grantMask) == 0);
4092  }
4093 
4094  /*
4095  * lock->nRequested and lock->requested[] count the total number of
4096  * requests, whether granted or waiting, so increment those immediately.
4097  */
4098  lock->nRequested++;
4099  lock->requested[lockmode]++;
4100  Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4101 
4102  /*
4103  * We shouldn't already hold the desired lock.
4104  */
4105  if (proclock->holdMask & LOCKBIT_ON(lockmode))
4106  elog(ERROR, "lock %s on object %u/%u/%u is already held",
4107  lockMethodTable->lockModeNames[lockmode],
4108  lock->tag.locktag_field1, lock->tag.locktag_field2,
4109  lock->tag.locktag_field3);
4110 
4111  /*
4112  * We ignore any possible conflicts and just grant ourselves the lock. Not
4113  * only because we don't bother, but also to avoid deadlocks when
4114  * switching from standby to normal mode. See function comment.
4115  */
4116  GrantLock(lock, proclock, lockmode);
4117 
4118  /*
4119  * Bump strong lock count, to make sure any fast-path lock requests won't
4120  * be granted without consulting the primary lock table.
4121  */
4122  if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4123  {
4124  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4125 
4127  FastPathStrongRelationLocks->count[fasthashcode]++;
4129  }
4130 
4131  LWLockRelease(partitionLock);
4132 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
PGPROC * TwoPhaseGetDummyProc(TransactionId xid)
Definition: twophase.c:868
Definition: lwlock.h:32
int errhint(const char *fmt,...)
Definition: elog.c:987
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
int LOCKMODE
Definition: lockdefs.h:26
int nRequested
Definition: lock.h:295
LOCKMASK holdMask
Definition: lock.h:351
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1415
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
LOCKTAG tag
Definition: lock.h:287
Definition: lock.h:178
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
SHM_QUEUE lockLink
Definition: lock.h:353
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:853
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
#define LockHashPartition(hashcode)
Definition: lock.h:495
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:600
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:297
PROC_QUEUE waitProcs
Definition: lock.h:293
LOCKTAG locktag
Definition: lock.c:160
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
void ProcQueueInit(PROC_QUEUE *queue)
Definition: proc.c:1013
uint32 locktag_field2
Definition: lock.h:181
unsigned int uint32
Definition: c.h:296
int granted[MAX_LOCKMODES]
Definition: lock.h:296
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define ereport(elevel, rest)
Definition: elog.h:122
LOCKMASK waitMask
Definition: lock.h:291
uint16 LOCKMETHODID
Definition: lock.h:125
SHM_QUEUE procLocks
Definition: lock.h:292
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define SpinLockRelease(lock)
Definition: spin.h:64
int requested[MAX_LOCKMODES]
Definition: lock.h:294
#define MAX_LOCKMODES
Definition: lock.h:85
SHM_QUEUE procLink
Definition: lock.h:354
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:670
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290
Definition: lock.h:344
int errmsg(const char *fmt,...)
Definition: elog.c:797
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
LOCK * myLock
Definition: lock.h:340
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:157
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
#define elog
Definition: elog.h:219
uint32 locktag_field1
Definition: lock.h:180
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:95
uint32 locktag_field3
Definition: lock.h:182
PGPROC * lockGroupLeader
Definition: proc.h:200
const char *const * lockModeNames
Definition: lock.h:115
PGPROC * groupLeader
Definition: lock.h:350
LOCKMASK releaseMask
Definition: lock.h:352

◆ lock_twophase_standby_recover()

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

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

4141 {
4142  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4143  LOCKTAG *locktag;
4144  LOCKMODE lockmode;
4145  LOCKMETHODID lockmethodid;
4146 
4147  Assert(len == sizeof(TwoPhaseLockRecord));
4148  locktag = &rec->locktag;
4149  lockmode = rec->lockmode;
4150  lockmethodid = locktag->locktag_lockmethodid;
4151 
4152  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4153  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4154 
4155  if (lockmode == AccessExclusiveLock &&
4156  locktag->locktag_type == LOCKTAG_RELATION)
4157  {
4159  locktag->locktag_field1 /* dboid */ ,
4160  locktag->locktag_field2 /* reloid */ );
4161  }
4162 }
int LOCKMODE
Definition: lockdefs.h:26
Definition: lock.h:178
#define lengthof(array)
Definition: c.h:600
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
uint32 locktag_field2
Definition: lock.h:181
uint16 LOCKMETHODID
Definition: lock.h:125
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:670
uint8 locktag_lockmethodid
Definition: lock.h:185
#define AccessExclusiveLock
Definition: lockdefs.h:45
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:602
static const LockMethod LockMethods[]
Definition: lock.c:150
#define elog
Definition: elog.h:219
uint32 locktag_field1
Definition: lock.h:180
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  report_memory_error 
)

Definition at line 701 of file lock.c.

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

Referenced by LockAcquire(), and StandbyAcquireAccessExclusiveLock().

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

◆ LockCheckConflicts()

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

Definition at line 1292 of file lock.c.

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

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

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

◆ LockHasWaiters()

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

Definition at line 571 of file lock.c.

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

Referenced by LockHasWaitersRelation().

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

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2413 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2414 {
2416 
2417  Assert(parent != NULL);
2418 
2419  if (locallocks == NULL)
2420  {
2422  LOCALLOCK *locallock;
2423 
2425 
2426  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2427  LockReassignOwner(locallock, parent);
2428  }
2429  else
2430  {
2431  int i;
2432 
2433  for (i = nlocks - 1; i >= 0; i--)
2434  LockReassignOwner(locallocks[i], parent);
2435  }
2436 }
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2443
static HTAB * LockMethodLocalHash
Definition: lock.c:255
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition: resowner.c:722
#define Assert(condition)
Definition: c.h:670
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ LockRelease()

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

Definition at line 1818 of file lock.c.

References Assert, PGPROC::backendLock, CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FastPathLocalUseCount, FastPathUnGrantRelationLock(), HASH_FIND, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PROCLOCK::holdMask, i, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, 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(), StandbyReleaseAllLocks(), StandbyReleaseLocks(), StandbyReleaseOldLocks(), UnlockDatabaseObject(), UnlockPage(), UnlockRelation(), UnlockRelationForExtension(), UnlockRelationId(), UnlockRelationIdForSession(), UnlockRelationOid(), UnlockSharedObject(), UnlockSharedObjectForSession(), UnlockTuple(), VirtualXactLock(), XactLockTableDelete(), and XactLockTableWait().

1819 {
1820  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
1821  LockMethod lockMethodTable;
1822  LOCALLOCKTAG localtag;
1823  LOCALLOCK *locallock;
1824  LOCK *lock;
1825  PROCLOCK *proclock;
1826  LWLock *partitionLock;
1827  bool wakeupNeeded;
1828 
1829  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
1830  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
1831  lockMethodTable = LockMethods[lockmethodid];
1832  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
1833  elog(ERROR, "unrecognized lock mode: %d", lockmode);
1834 
1835 #ifdef LOCK_DEBUG
1836  if (LOCK_DEBUG_ENABLED(locktag))
1837  elog(LOG, "LockRelease: lock [%u,%u] %s",
1838  locktag->locktag_field1, locktag->locktag_field2,
1839  lockMethodTable->lockModeNames[lockmode]);
1840 #endif
1841 
1842  /*
1843  * Find the LOCALLOCK entry for this lock and lockmode
1844  */
1845  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
1846  localtag.lock = *locktag;
1847  localtag.mode = lockmode;
1848 
1849  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
1850  (void *) &localtag,
1851  HASH_FIND, NULL);
1852 
1853  /*
1854  * let the caller print its own error message, too. Do not ereport(ERROR).
1855  */
1856  if (!locallock || locallock->nLocks <= 0)
1857  {
1858  elog(WARNING, "you don't own a lock of type %s",
1859  lockMethodTable->lockModeNames[lockmode]);
1860  return false;
1861  }
1862 
1863  /*
1864  * Decrease the count for the resource owner.
1865  */
1866  {
1867  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1868  ResourceOwner owner;
1869  int i;
1870 
1871  /* Identify owner for lock */
1872  if (sessionLock)
1873  owner = NULL;
1874  else
1875  owner = CurrentResourceOwner;
1876 
1877  for (i = locallock->numLockOwners - 1; i >= 0; i--)
1878  {
1879  if (lockOwners[i].owner == owner)
1880  {
1881  Assert(lockOwners[i].nLocks > 0);
1882  if (--lockOwners[i].nLocks == 0)
1883  {
1884  if (owner != NULL)
1885  ResourceOwnerForgetLock(owner, locallock);
1886  /* compact out unused slot */
1887  locallock->numLockOwners--;
1888  if (i < locallock->numLockOwners)
1889  lockOwners[i] = lockOwners[locallock->numLockOwners];
1890  }
1891  break;
1892  }
1893  }
1894  if (i < 0)
1895  {
1896  /* don't release a lock belonging to another owner */
1897  elog(WARNING, "you don't own a lock of type %s",
1898  lockMethodTable->lockModeNames[lockmode]);
1899  return false;
1900  }
1901  }
1902 
1903  /*
1904  * Decrease the total local count. If we're still holding the lock, we're
1905  * done.
1906  */
1907  locallock->nLocks--;
1908 
1909  if (locallock->nLocks > 0)
1910  return true;
1911 
1912  /* Attempt fast release of any lock eligible for the fast path. */
1913  if (EligibleForRelationFastPath(locktag, lockmode) &&
1915  {
1916  bool released;
1917 
1918  /*
1919  * We might not find the lock here, even if we originally entered it
1920  * here. Another backend may have moved it to the main table.
1921  */
1923  released = FastPathUnGrantRelationLock(locktag->locktag_field2,
1924  lockmode);
1926  if (released)
1927  {
1928  RemoveLocalLock(locallock);
1929  return true;
1930  }
1931  }
1932 
1933  /*
1934  * Otherwise we've got to mess with the shared lock table.
1935  */
1936  partitionLock = LockHashPartitionLock(locallock->hashcode);
1937 
1938  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
1939 
1940  /*
1941  * Normally, we don't need to re-find the lock or proclock, since we kept
1942  * their addresses in the locallock table, and they couldn't have been
1943  * removed while we were holding a lock on them. But it's possible that
1944  * the lock was taken fast-path and has since been moved to the main hash
1945  * table by another backend, in which case we will need to look up the
1946  * objects here. We assume the lock field is NULL if so.
1947  */
1948  lock = locallock->lock;
1949  if (!lock)
1950  {
1951  PROCLOCKTAG proclocktag;
1952 
1953  Assert(EligibleForRelationFastPath(locktag, lockmode));
1955  (const void *) locktag,
1956  locallock->hashcode,
1957  HASH_FIND,
1958  NULL);
1959  if (!lock)
1960  elog(ERROR, "failed to re-find shared lock object");
1961  locallock->lock = lock;
1962 
1963  proclocktag.myLock = lock;
1964  proclocktag.myProc = MyProc;
1966  (void *) &proclocktag,
1967  HASH_FIND,
1968  NULL);
1969  if (!locallock->proclock)
1970  elog(ERROR, "failed to re-find shared proclock object");
1971  }
1972  LOCK_PRINT("LockRelease: found", lock, lockmode);
1973  proclock = locallock->proclock;
1974  PROCLOCK_PRINT("LockRelease: found", proclock);
1975 
1976  /*
1977  * Double-check that we are actually holding a lock of the type we want to
1978  * release.
1979  */
1980  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
1981  {
1982  PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
1983  LWLockRelease(partitionLock);
1984  elog(WARNING, "you don't own a lock of type %s",
1985  lockMethodTable->lockModeNames[lockmode]);
1986  RemoveLocalLock(locallock);
1987  return false;
1988  }
1989 
1990  /*
1991  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
1992  */
1993  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
1994 
1995  CleanUpLock(lock, proclock,
1996  lockMethodTable, locallock->hashcode,
1997  wakeupNeeded);
1998 
1999  LWLockRelease(partitionLock);
2000 
2001  RemoveLocalLock(locallock);
2002  return true;
2003 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
uint32 hashcode
Definition: lock.h:409
Definition: lwlock.h:32
static HTAB * LockMethodLocalHash
Definition: lock.c:255
int numLockOwners
Definition: lock.h:411
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2526
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static int FastPathLocalUseCount
Definition: lock.c:171
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
#define MemSet(start, val, len)
Definition: c.h:853
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:600
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:902
#define LOG
Definition: elog.h:26
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:199
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1244
uint32 locktag_field2
Definition: lock.h:181
Definition: lock.h:284
uint16 LOCKMETHODID
Definition: lock.h:125
#define WARNING
Definition: elog.h:40
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:895
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:670
LWLock backendLock
Definition: proc.h:187
static HTAB * LockMethodLockHash
Definition: lock.c:253
LOCALLOCKOWNER * lockOwners
Definition: lock.h:414
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
LOCK * lock
Definition: lock.h:407
uint8 locktag_lockmethodid
Definition: lock.h:185
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
int i
LOCK * myLock
Definition: lock.h:340
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1438
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
#define elog
Definition: elog.h:219
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1495
uint32 locktag_field1
Definition: lock.h:180
const char *const * lockModeNames
Definition: lock.h:115
int numLockModes
Definition: lock.h:113

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2014 of file lock.c.

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

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

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

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2318 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2319 {
2320  if (locallocks == NULL)
2321  {
2323  LOCALLOCK *locallock;
2324 
2326 
2327  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2328  ReleaseLockIfHeld(locallock, false);
2329  }
2330  else
2331  {
2332  int i;
2333 
2334  for (i = nlocks - 1; i >= 0; i--)
2335  ReleaseLockIfHeld(locallocks[i], false);
2336  }
2337 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2353
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

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

2289 {
2291  LOCALLOCK *locallock;
2292 
2293  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2294  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2295 
2297 
2298  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2299  {
2300  /* Ignore items that are not of the specified lock method */
2301  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2302  continue;
2303 
2304  ReleaseLockIfHeld(locallock, true);
2305  }
2306 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
#define lengthof(array)
Definition: c.h:600
#define ERROR
Definition: elog.h:43
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2353
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:417
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
static const LockMethod LockMethods[]
Definition: lock.c:150
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ LockShmemSize()

Size LockShmemSize ( void  )

Definition at line 3361 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

3362 {
3363  Size size = 0;
3364  long max_table_size;
3365 
3366  /* lock hash table */
3367  max_table_size = NLOCKENTS();
3368  size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3369 
3370  /* proclock hash table */
3371  max_table_size *= 2;
3372  size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3373 
3374  /*
3375  * Since NLOCKENTS is only an estimate, add 10% safety margin.
3376  */
3377  size = add_size(size, size / 10);
3378 
3379  return size;
3380 }
#define NLOCKENTS()
Definition: lock.c:56
Definition: lock.h:284
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:728
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:404
Definition: lock.h:344

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 490 of file lock.c.

References get_hash_value().

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

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

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

4388 {
4389  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4390  LOCK *lock;
4391  bool found;
4392  uint32 hashcode;
4393  LWLock *partitionLock;
4394  int waiters = 0;
4395 
4396  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4397  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4398 
4399  hashcode = LockTagHashCode(locktag);
4400  partitionLock = LockHashPartitionLock(hashcode);
4401  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4402 
4404  (const void *) locktag,
4405  hashcode,
4406  HASH_FIND,
4407  &found);
4408  if (found)
4409  {
4410  Assert(lock != NULL);
4411  waiters = lock->nRequested;
4412  }
4413  LWLockRelease(partitionLock);
4414 
4415  return waiters;
4416 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
Definition: lwlock.h:32
int nRequested
Definition: lock.h:295
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
#define lengthof(array)
Definition: c.h:600
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:296
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:670
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
uint8 locktag_lockmethodid
Definition: lock.h:185
static const LockMethod LockMethods[]
Definition: lock.c:150
#define elog
Definition: elog.h:219

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

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

3170 {
3171  PGPROC *newproc = TwoPhaseGetDummyProc(xid);
3173  LOCALLOCK *locallock;
3174  LOCK *lock;
3175  PROCLOCK *proclock;
3176  PROCLOCKTAG proclocktag;
3177  int partition;
3178 
3179  /* Can't prepare a lock group follower. */
3180  Assert(MyProc->lockGroupLeader == NULL ||
3182 
3183  /* This is a critical section: any error means big trouble */
3185 
3186  /*
3187  * First we run through the locallock table and get rid of unwanted
3188  * entries, then we scan the process's proclocks and transfer them to the
3189  * target proc.
3190  *
3191  * We do this separately because we may have multiple locallock entries
3192  * pointing to the same proclock, and we daren't end up with any dangling
3193  * pointers.
3194  */
3196 
3197  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3198  {
3199  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3200  bool haveSessionLock;
3201  bool haveXactLock;
3202  int i;
3203 
3204  if (locallock->proclock == NULL || locallock->lock == NULL)
3205  {
3206  /*
3207  * We must've run out of shared memory while trying to set up this
3208  * lock. Just forget the local entry.
3209  */
3210  Assert(locallock->nLocks == 0);
3211  RemoveLocalLock(locallock);
3212  continue;
3213  }
3214 
3215  /* Ignore VXID locks */
3216  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3217  continue;
3218 
3219  /* Scan to see whether we hold it at session or transaction level */
3220  haveSessionLock = haveXactLock = false;
3221  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3222  {
3223  if (lockOwners[i].owner == NULL)
3224  haveSessionLock = true;
3225  else
3226  haveXactLock = true;
3227  }
3228 
3229  /* Ignore it if we have only session lock */
3230  if (!haveXactLock)
3231  continue;
3232 
3233  /* This can't happen, because we already checked it */
3234  if (haveSessionLock)
3235  ereport(PANIC,
3236  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3237  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3238 
3239  /* Mark the proclock to show we need to release this lockmode */
3240  if (locallock->nLocks > 0)
3241  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3242 
3243  /* And remove the locallock hashtable entry */
3244  RemoveLocalLock(locallock);
3245  }
3246 
3247  /*
3248  * Now, scan each lock partition separately.
3249  */
3250  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3251  {
3252  LWLock *partitionLock;
3253  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
3254  PROCLOCK *nextplock;
3255 
3256  partitionLock = LockHashPartitionLockByIndex(partition);
3257 
3258  /*
3259  * If the proclock list for this partition is empty, we can skip
3260  * acquiring the partition lock. This optimization is safer than the
3261  * situation in LockReleaseAll, because we got rid of any fast-path
3262  * locks during AtPrepare_Locks, so there cannot be any case where
3263  * another backend is adding something to our lists now. For safety,
3264  * though, we code this the same way as in LockReleaseAll.
3265  */
3266  if (SHMQueueNext(procLocks, procLocks,
3267  offsetof(PROCLOCK, procLink)) == NULL)
3268  continue; /* needn't examine this partition */
3269 
3270  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3271 
3272  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3273  offsetof(PROCLOCK, procLink));
3274  proclock;
3275  proclock = nextplock)
3276  {
3277  /* Get link first, since we may unlink/relink this proclock */
3278  nextplock = (PROCLOCK *)
3279  SHMQueueNext(procLocks, &proclock->procLink,
3280  offsetof(PROCLOCK, procLink));
3281 
3282  Assert(proclock->tag.myProc == MyProc);
3283 
3284  lock = proclock->tag.myLock;
3285 
3286  /* Ignore VXID locks */
3288  continue;
3289 
3290  PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3291  LOCK_PRINT("PostPrepare_Locks", lock, 0);
3292  Assert(lock->nRequested >= 0);
3293  Assert(lock->nGranted >= 0);
3294  Assert(lock->nGranted <= lock->nRequested);
3295  Assert((proclock->holdMask & ~lock->grantMask) == 0);
3296 
3297  /* Ignore it if nothing to release (must be a session lock) */
3298  if (proclock->releaseMask == 0)
3299  continue;
3300 
3301  /* Else we should be releasing all locks */
3302  if (proclock->releaseMask != proclock->holdMask)
3303  elog(PANIC, "we seem to have dropped a bit somewhere");
3304 
3305  /*
3306  * We cannot simply modify proclock->tag.myProc to reassign
3307  * ownership of the lock, because that's part of the hash key and
3308  * the proclock would then be in the wrong hash chain. Instead
3309  * use hash_update_hash_key. (We used to create a new hash entry,
3310  * but that risks out-of-memory failure if other processes are
3311  * busy making proclocks too.) We must unlink the proclock from
3312  * our procLink chain and put it into the new proc's chain, too.
3313  *
3314  * Note: the updated proclock hash key will still belong to the
3315  * same hash partition, cf proclock_hash(). So the partition lock
3316  * we already hold is sufficient for this.
3317  */
3318  SHMQueueDelete(&proclock->procLink);
3319 
3320  /*
3321  * Create the new hash key for the proclock.
3322  */
3323  proclocktag.myLock = lock;
3324  proclocktag.myProc = newproc;
3325 
3326  /*
3327  * Update groupLeader pointer to point to the new proc. (We'd
3328  * better not be a member of somebody else's lock group!)
3329  */
3330  Assert(proclock->groupLeader == proclock->tag.myProc);
3331  proclock->groupLeader = newproc;
3332 
3333  /*
3334  * Update the proclock. We should not find any existing entry for
3335  * the same hash key, since there can be only one entry for any
3336  * given lock with my own proc.
3337  */
3339  (void *) proclock,
3340  (void *) &proclocktag))
3341  elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3342 
3343  /* Re-link into the new proc's proclock list */
3344  SHMQueueInsertBefore(&(newproc->myProcLocks[partition]),
3345  &proclock->procLink);
3346 
3347  PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3348  } /* loop over PROCLOCKs within this partition */
3349 
3350  LWLockRelease(partitionLock);
3351  } /* loop over partitions */
3352 
3353  END_CRIT_SECTION();
3354 }
PROCLOCKTAG tag
Definition: lock.h:347
PGPROC * TwoPhaseGetDummyProc(TransactionId xid)
Definition: twophase.c:868
Definition: lwlock.h:32
LOCALLOCKTAG tag
Definition: lock.h:404
static HTAB * LockMethodLocalHash
Definition: lock.c:255
int numLockOwners
Definition: lock.h:411
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
PROCLOCK * proclock
Definition: lock.h:408
int nRequested
Definition: lock.h:295
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:351
LOCKTAG tag
Definition: lock.h:287
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:297
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:500
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1244
Definition: lock.h:284
#define ereport(elevel, rest)
Definition: elog.h:122
SHM_QUEUE procLink
Definition: lock.h:354
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
uint8 locktag_type
Definition: lock.h:184
#define Assert(condition)
Definition: c.h:670
LOCALLOCKOWNER * lockOwners
Definition: lock.h:414
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr)
Definition: dynahash.c:1111
LOCK * lock
Definition: lock.h:407
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1385
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1375
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
LOCKMASK grantMask
Definition: lock.h:290
Definition: lock.h:344
int64 nLocks
Definition: lock.h:410
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
LOCK * myLock
Definition: lock.h:340
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:157
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Definition: proc.h:95
PGPROC * lockGroupLeader
Definition: proc.h:200
#define offsetof(type, field)
Definition: c.h:593
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
PGPROC * groupLeader
Definition: lock.h:350
LOCKMASK releaseMask
Definition: lock.h:352

◆ RememberSimpleDeadLock()

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

Definition at line 1149 of file deadlock.c.

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

Referenced by ProcSleep().

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

◆ RemoveFromWaitQueue()

void RemoveFromWaitQueue ( PGPROC proc,
uint32  hashcode 
)

Definition at line 1761 of file lock.c.

References Assert, CleanUpLock(), LOCK::granted, lengthof, PGPROC::links, LOCK_LOCKMETHOD, LOCKBIT_OFF, TwoPhaseLockRecord::lockmode, SHM_QUEUE::next, LOCK::nGranted, LOCK::nRequested, LOCK::requested, SHMQueueDelete(), PROC_QUEUE::size, STATUS_ERROR, STATUS_WAITING, PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, and PGPROC::waitStatus.

Referenced by CheckDeadLock(), LockErrorCleanup(), and ProcSleep().

1762 {
1763  LOCK *waitLock = proc->waitLock;
1764  PROCLOCK *proclock = proc->waitProcLock;
1765  LOCKMODE lockmode = proc->waitLockMode;
1766  LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*waitLock);
1767 
1768  /* Make sure proc is waiting */
1769  Assert(proc->waitStatus == STATUS_WAITING);
1770  Assert(proc->links.next != NULL);
1771  Assert(waitLock);
1772  Assert(waitLock->waitProcs.size > 0);
1773  Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
1774 
1775  /* Remove proc from lock's wait queue */
1776  SHMQueueDelete(&(proc->links));
1777  waitLock->waitProcs.size--;
1778 
1779  /* Undo increments of request counts by waiting process */
1780  Assert(waitLock->nRequested > 0);
1781  Assert(waitLock->nRequested > proc->waitLock->nGranted);
1782  waitLock->nRequested--;
1783  Assert(waitLock->requested[lockmode] > 0);
1784  waitLock->requested[lockmode]--;
1785  /* don't forget to clear waitMask bit if appropriate */
1786  if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
1787  waitLock->waitMask &= LOCKBIT_OFF(lockmode);
1788 
1789  /* Clean up the proc's own state, and pass it the ok/fail signal */
1790  proc->waitLock = NULL;
1791  proc->waitProcLock = NULL;
1792  proc->waitStatus = STATUS_ERROR;
1793 
1794  /*
1795  * Delete the proclock immediately if it represents no already-held locks.
1796  * (This must happen now because if the owner of the lock decides to
1797  * release it, and the requested/granted counts then go to zero,
1798  * LockRelease expects there to be no remaining proclocks.) Then see if
1799  * any other waiters for the lock can be woken up now.
1800  */
1801  CleanUpLock(waitLock, proclock,
1802  LockMethods[lockmethodid], hashcode,
1803  true);
1804 }
int LOCKMODE
Definition: lockdefs.h:26
int nRequested
Definition: lock.h:295