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

Go to the source code of this file.

Data Structures

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

Macros

#define InvalidLocalTransactionId   0
 
#define LocalTransactionIdIsValid(lxid)   ((lxid) != InvalidLocalTransactionId)
 
#define VirtualTransactionIdIsValid(vxid)    (LocalTransactionIdIsValid((vxid).localTransactionId))
 
#define VirtualTransactionIdIsRecoveredPreparedXact(vxid)    ((vxid).procNumber == INVALID_PROC_NUMBER)
 
#define VirtualTransactionIdEquals(vxid1, vxid2)
 
#define SetInvalidVirtualTransactionId(vxid)
 
#define GET_VXID_FROM_PGPROC(vxid_dst, 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_APPLY_TRANSACTION
 
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
 
#define SET_LOCKTAG_RELATION_EXTEND(locktag, dboid, reloid)
 
#define SET_LOCKTAG_DATABASE_FROZEN_IDS(locktag, dboid)
 
#define SET_LOCKTAG_PAGE(locktag, dboid, reloid, blocknum)
 
#define SET_LOCKTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
 
#define SET_LOCKTAG_TRANSACTION(locktag, xid)
 
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
 
#define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag, xid, token)
 
#define SET_LOCKTAG_OBJECT(locktag, dboid, classoid, objoid, objsubid)
 
#define SET_LOCKTAG_ADVISORY(locktag, id1, id2, id3, id4)
 
#define SET_LOCKTAG_APPLY_TRANSACTION(locktag, dboid, suboid, xid, objid)
 
#define LOCK_LOCKMETHOD(lock)   ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
 
#define LOCK_LOCKTAG(lock)   ((LockTagType) (lock).tag.locktag_type)
 
#define PROCLOCK_LOCKMETHOD(proclock)    LOCK_LOCKMETHOD(*((proclock).tag.myLock))
 
#define LOCALLOCK_LOCKMETHOD(llock)   ((llock).tag.lock.locktag_lockmethodid)
 
#define LOCALLOCK_LOCKTAG(llock)   ((LockTagType) (llock).tag.lock.locktag_type)
 
#define LockHashPartition(hashcode)    ((hashcode) % NUM_LOCK_PARTITIONS)
 
#define LockHashPartitionLock(hashcode)
 
#define LockHashPartitionLockByIndex(i)    (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
 
#define LockHashPartitionLockByProc(leader_pgproc)    LockHashPartitionLock(GetNumberFromPGProc(leader_pgproc))
 

Typedefs

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

Enumerations

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

Functions

void LockManagerShmemInit (void)
 
Size LockManagerShmemSize (void)
 
void InitLockManagerAccess (void)
 
LockMethod GetLocksMethodTable (const LOCK *lock)
 
LockMethod GetLockTagsMethodTable (const LOCKTAG *locktag)
 
uint32 LockTagHashCode (const LOCKTAG *locktag)
 
bool DoLockModesConflict (LOCKMODE mode1, LOCKMODE mode2)
 
LockAcquireResult LockAcquire (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
 
LockAcquireResult LockAcquireExtended (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
 
void AbortStrongLockAcquire (void)
 
void MarkLockClear (LOCALLOCK *locallock)
 
bool LockRelease (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
void LockReleaseAll (LOCKMETHODID lockmethodid, bool allLocks)
 
void LockReleaseSession (LOCKMETHODID lockmethodid)
 
void LockReleaseCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
void LockReassignCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
bool LockHeldByMe (const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
 
bool LockHasWaiters (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
VirtualTransactionIdGetLockConflicts (const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
 
void AtPrepare_Locks (void)
 
void PostPrepare_Locks (TransactionId xid)
 
bool LockCheckConflicts (LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
 
void GrantLock (LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
 
void GrantAwaitedLock (void)
 
LOCALLOCKGetAwaitedLock (void)
 
void ResetAwaitedLock (void)
 
void RemoveFromWaitQueue (PGPROC *proc, uint32 hashcode)
 
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)
 
pg_noreturn void DeadLockReport (void)
 
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

PGDLLIMPORT int max_locks_per_xact
 
PGDLLIMPORT bool log_lock_failure
 
PGDLLIMPORT const char *const LockTagTypeNames []
 

Macro Definition Documentation

◆ DEFAULT_LOCKMETHOD

#define DEFAULT_LOCKMETHOD   1

Definition at line 126 of file lock.h.

◆ GET_VXID_FROM_PGPROC

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

Definition at line 78 of file lock.h.

◆ InvalidLocalTransactionId

#define InvalidLocalTransactionId   0

Definition at line 66 of file lock.h.

◆ LOCALLOCK_LOCKMETHOD

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

Definition at line 444 of file lock.h.

◆ LOCALLOCK_LOCKTAG

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

Definition at line 445 of file lock.h.

◆ LocalTransactionIdIsValid

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

Definition at line 67 of file lock.h.

◆ LOCK_LOCKMETHOD

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

Definition at line 325 of file lock.h.

◆ LOCK_LOCKTAG

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

Definition at line 326 of file lock.h.

◆ LOCKBIT_OFF

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

Definition at line 86 of file lock.h.

◆ LOCKBIT_ON

#define LOCKBIT_ON (   lockmode)    (1 << (lockmode))

Definition at line 85 of file lock.h.

◆ LockHashPartition

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

Definition at line 525 of file lock.h.

◆ LockHashPartitionLock

#define LockHashPartitionLock (   hashcode)
Value:
LockHashPartition(hashcode)].lock)
LWLockPadded * MainLWLockArray
Definition: lwlock.c:202
#define LOCK_MANAGER_LWLOCK_OFFSET
Definition: lwlock.h:105
LWLock lock
Definition: lwlock.h:70

Definition at line 527 of file lock.h.

◆ LockHashPartitionLockByIndex

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

Definition at line 530 of file lock.h.

◆ LockHashPartitionLockByProc

#define LockHashPartitionLockByProc (   leader_pgproc)     LockHashPartitionLock(GetNumberFromPGProc(leader_pgproc))

Definition at line 542 of file lock.h.

◆ LOCKTAG_LAST_TYPE

#define LOCKTAG_LAST_TYPE   LOCKTAG_APPLY_TRANSACTION

Definition at line 153 of file lock.h.

◆ MAX_LOCKMODES

#define MAX_LOCKMODES   10

Definition at line 83 of file lock.h.

◆ PROCLOCK_LOCKMETHOD

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

Definition at line 383 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)
@ LOCKTAG_ADVISORY
Definition: lock.h:148
#define USER_LOCKMETHOD
Definition: lock.h:127

Definition at line 271 of file lock.h.

◆ SET_LOCKTAG_APPLY_TRANSACTION

#define SET_LOCKTAG_APPLY_TRANSACTION (   locktag,
  dboid,
  suboid,
  xid,
  objid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (suboid), \
(locktag).locktag_field3 = (xid), \
(locktag).locktag_field4 = (objid), \
(locktag).locktag_type = LOCKTAG_APPLY_TRANSACTION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition: lock.h:126
@ LOCKTAG_APPLY_TRANSACTION
Definition: lock.h:149

Definition at line 283 of file lock.h.

◆ SET_LOCKTAG_DATABASE_FROZEN_IDS

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

Definition at line 200 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)
@ LOCKTAG_OBJECT
Definition: lock.h:146

Definition at line 263 of file lock.h.

◆ 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)
@ LOCKTAG_PAGE
Definition: lock.h:141

Definition at line 209 of file lock.h.

◆ 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)
@ LOCKTAG_RELATION
Definition: lock.h:138

Definition at line 182 of file lock.h.

◆ 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)
@ LOCKTAG_RELATION_EXTEND
Definition: lock.h:139

Definition at line 191 of file lock.h.

◆ 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)
@ LOCKTAG_SPECULATIVE_TOKEN
Definition: lock.h:145

Definition at line 248 of file lock.h.

◆ 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)
@ LOCKTAG_TRANSACTION
Definition: lock.h:143

Definition at line 227 of file lock.h.

◆ 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)
@ LOCKTAG_TUPLE
Definition: lock.h:142

Definition at line 218 of file lock.h.

◆ SET_LOCKTAG_VIRTUALTRANSACTION

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

Definition at line 236 of file lock.h.

◆ SetInvalidVirtualTransactionId

#define SetInvalidVirtualTransactionId (   vxid)
Value:
((vxid).procNumber = INVALID_PROC_NUMBER, \
(vxid).localTransactionId = InvalidLocalTransactionId)
#define InvalidLocalTransactionId
Definition: lock.h:66
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26

Definition at line 75 of file lock.h.

◆ USER_LOCKMETHOD

#define USER_LOCKMETHOD   2

Definition at line 127 of file lock.h.

◆ VirtualTransactionIdEquals

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

Definition at line 72 of file lock.h.

◆ VirtualTransactionIdIsRecoveredPreparedXact

#define VirtualTransactionIdIsRecoveredPreparedXact (   vxid)     ((vxid).procNumber == INVALID_PROC_NUMBER)

Definition at line 70 of file lock.h.

◆ VirtualTransactionIdIsValid

#define VirtualTransactionIdIsValid (   vxid)     (LocalTransactionIdIsValid((vxid).localTransactionId))

Definition at line 68 of file lock.h.

Typedef Documentation

◆ BlockedProcData

◆ BlockedProcsData

◆ LOCALLOCK

typedef struct LOCALLOCK LOCALLOCK

◆ LOCALLOCKOWNER

◆ LOCALLOCKTAG

typedef struct LOCALLOCKTAG LOCALLOCKTAG

◆ LOCK

typedef struct LOCK LOCK

◆ LockData

typedef struct LockData LockData

◆ LockInstanceData

◆ LockMethod

typedef const LockMethodData* LockMethod

Definition at line 117 of file lock.h.

◆ LockMethodData

◆ LOCKMETHODID

Definition at line 123 of file lock.h.

◆ LOCKTAG

typedef struct LOCKTAG LOCKTAG

◆ LockTagType

typedef enum LockTagType LockTagType

◆ PGPROC

typedef struct PGPROC PGPROC

Definition at line 29 of file lock.h.

◆ PROCLOCK

typedef struct PROCLOCK PROCLOCK

◆ PROCLOCKTAG

typedef struct PROCLOCKTAG PROCLOCKTAG

Enumeration Type Documentation

◆ DeadLockState

Enumerator
DS_NOT_YET_CHECKED 
DS_NO_DEADLOCK 
DS_SOFT_DEADLOCK 
DS_HARD_DEADLOCK 
DS_BLOCKED_BY_AUTOVACUUM 

Definition at line 509 of file lock.h.

510{
511 DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
512 DS_NO_DEADLOCK, /* no deadlock detected */
513 DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
514 DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
515 DS_BLOCKED_BY_AUTOVACUUM, /* no deadlock; queue blocked by autovacuum
516 * worker */
DeadLockState
Definition: lock.h:510
@ DS_HARD_DEADLOCK
Definition: lock.h:514
@ DS_BLOCKED_BY_AUTOVACUUM
Definition: lock.h:515
@ DS_NO_DEADLOCK
Definition: lock.h:512
@ DS_NOT_YET_CHECKED
Definition: lock.h:511
@ DS_SOFT_DEADLOCK
Definition: lock.h:513

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 
LOCKACQUIRE_ALREADY_CLEAR 

Definition at line 500 of file lock.h.

501{
502 LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
503 LOCKACQUIRE_OK, /* lock successfully acquired */
504 LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
505 LOCKACQUIRE_ALREADY_CLEAR, /* incremented count for lock already clear */
LockAcquireResult
Definition: lock.h:501
@ LOCKACQUIRE_ALREADY_CLEAR
Definition: lock.h:505
@ LOCKACQUIRE_OK
Definition: lock.h:503
@ LOCKACQUIRE_ALREADY_HELD
Definition: lock.h:504
@ LOCKACQUIRE_NOT_AVAIL
Definition: lock.h:502

◆ LockTagType

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

Definition at line 136 of file lock.h.

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

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )

Definition at line 1859 of file lock.c.

1860{
1861 uint32 fasthashcode;
1862 LOCALLOCK *locallock = StrongLockInProgress;
1863
1864 if (locallock == NULL)
1865 return;
1866
1867 fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1868 Assert(locallock->holdsStrongLockCount == true);
1870 Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1871 FastPathStrongRelationLocks->count[fasthashcode]--;
1872 locallock->holdsStrongLockCount = false;
1873 StrongLockInProgress = NULL;
1875}
uint32_t uint32
Definition: c.h:502
Assert(PointerIsAligned(start, uint64))
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:303
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:312
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:327
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:309
uint32 hashcode
Definition: lock.h:433
bool holdsStrongLockCount
Definition: lock.h:440

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

Definition at line 3446 of file lock.c.

3447{
3448 HASH_SEQ_STATUS status;
3449 LOCALLOCK *locallock;
3450
3451 /* First, verify there aren't locks of both xact and session level */
3453
3454 /* Now do the per-locallock cleanup work */
3456
3457 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3458 {
3459 TwoPhaseLockRecord record;
3460 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3461 bool haveSessionLock;
3462 bool haveXactLock;
3463 int i;
3464
3465 /*
3466 * Ignore VXID locks. We don't want those to be held by prepared
3467 * transactions, since they aren't meaningful after a restart.
3468 */
3470 continue;
3471
3472 /* Ignore it if we don't actually hold the lock */
3473 if (locallock->nLocks <= 0)
3474 continue;
3475
3476 /* Scan to see whether we hold it at session or transaction level */
3477 haveSessionLock = haveXactLock = false;
3478 for (i = locallock->numLockOwners - 1; i >= 0; i--)
3479 {
3480 if (lockOwners[i].owner == NULL)
3481 haveSessionLock = true;
3482 else
3483 haveXactLock = true;
3484 }
3485
3486 /* Ignore it if we have only session lock */
3487 if (!haveXactLock)
3488 continue;
3489
3490 /* This can't happen, because we already checked it */
3491 if (haveSessionLock)
3492 ereport(ERROR,
3493 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3494 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3495
3496 /*
3497 * If the local lock was taken via the fast-path, we need to move it
3498 * to the primary lock table, or just get a pointer to the existing
3499 * primary lock table entry if by chance it's already been
3500 * transferred.
3501 */
3502 if (locallock->proclock == NULL)
3503 {
3504 locallock->proclock = FastPathGetRelationLockEntry(locallock);
3505 locallock->lock = locallock->proclock->tag.myLock;
3506 }
3507
3508 /*
3509 * Arrange to not release any strong lock count held by this lock
3510 * entry. We must retain the count until the prepared transaction is
3511 * committed or rolled back.
3512 */
3513 locallock->holdsStrongLockCount = false;
3514
3515 /*
3516 * Create a 2PC record.
3517 */
3518 memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3519 record.lockmode = locallock->tag.mode;
3520
3522 &record, sizeof(TwoPhaseLockRecord));
3523 }
3524}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1421
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1386
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int i
Definition: isn.c:77
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition: lock.c:2926
static HTAB * LockMethodLocalHash
Definition: lock.c:323
static void CheckForSessionAndXactLocks(void)
Definition: lock.c:3358
LOCKTAG lock
Definition: lock.h:411
LOCKMODE mode
Definition: lock.h:412
LOCALLOCKOWNER * lockOwners
Definition: lock.h:439
LOCK * lock
Definition: lock.h:434
int64 nLocks
Definition: lock.h:436
int numLockOwners
Definition: lock.h:437
PROCLOCK * proclock
Definition: lock.h:435
LOCALLOCKTAG tag
Definition: lock.h:430
Definition: lock.h:166
uint8 locktag_type
Definition: lock.h:171
LOCK * myLock
Definition: lock.h:366
PROCLOCKTAG tag
Definition: lock.h:373
LOCKTAG locktag
Definition: lock.c:160
LOCKMODE lockmode
Definition: lock.c:161
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1264
#define TWOPHASE_RM_LOCK_ID
Definition: twophase_rmgr.h:25

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

Referenced by PrepareTransaction().

◆ DeadLockCheck()

DeadLockState DeadLockCheck ( PGPROC proc)

Definition at line 220 of file deadlock.c.

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 (int 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 dclist_head *waitQueue = &lock->waitProcs;
255
256 Assert(nProcs == dclist_count(waitQueue));
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 dclist_init(waitQueue);
264 for (int j = 0; j < nProcs; j++)
265 dclist_push_tail(waitQueue, &procs[j]->links);
266
267#ifdef DEBUG_DEADLOCK
268 PrintLockQueue(lock, "rearranged to:");
269#endif
270
271 /* See if any waiters for the lock can be woken up now */
273 }
274
275 /* Return code tells caller if we had to escape a deadlock or not */
276 if (nWaitOrders > 0)
277 return DS_SOFT_DEADLOCK;
278 else if (blocking_autovacuum_proc != NULL)
280 else
281 return DS_NO_DEADLOCK;
282}
static WAIT_ORDER * waitOrders
Definition: deadlock.c:112
static bool FindLockCycle(PGPROC *checkProc, EDGE *softEdges, int *nSoftEdges)
Definition: deadlock.c:446
static bool DeadLockCheckRecurse(PGPROC *proc)
Definition: deadlock.c:312
static EDGE * possibleConstraints
Definition: deadlock.c:122
static int nWaitOrders
Definition: deadlock.c:113
static int nCurConstraints
Definition: deadlock.c:118
static PGPROC * blocking_autovacuum_proc
Definition: deadlock.c:129
static int nPossibleConstraints
Definition: deadlock.c:123
#define FATAL
Definition: elog.h:41
#define elog(elevel,...)
Definition: elog.h:225
static void dclist_push_tail(dclist_head *head, dlist_node *node)
Definition: ilist.h:709
static uint32 dclist_count(const dclist_head *head)
Definition: ilist.h:932
static void dclist_init(dclist_head *head)
Definition: ilist.h:671
int j
Definition: isn.c:78
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition: lock.c:526
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1740
Definition: lock.h:310
dclist_head waitProcs
Definition: lock.h:318
Definition: proc.h:171
PGPROC ** procs
Definition: deadlock.c:60
LOCK * lock
Definition: deadlock.c:59
int nProcs
Definition: deadlock.c:61
static struct link * links
Definition: zic.c:299

References Assert(), blocking_autovacuum_proc, dclist_count(), dclist_init(), dclist_push_tail(), DeadLockCheckRecurse(), DS_BLOCKED_BY_AUTOVACUUM, DS_HARD_DEADLOCK, DS_NO_DEADLOCK, DS_SOFT_DEADLOCK, elog, FATAL, FindLockCycle(), GetLocksMethodTable(), i, j, links, WAIT_ORDER::lock, nCurConstraints, nPossibleConstraints, WAIT_ORDER::nProcs, nWaitOrders, possibleConstraints, ProcLockWakeup(), WAIT_ORDER::procs, waitOrders, and LOCK::waitProcs.

Referenced by CheckDeadLock().

◆ DeadLockReport()

pg_noreturn void DeadLockReport ( void  )

Definition at line 1075 of file deadlock.c.

1076{
1077 StringInfoData clientbuf; /* errdetail for client */
1078 StringInfoData logbuf; /* errdetail for server log */
1079 StringInfoData locktagbuf;
1080 int i;
1081
1082 initStringInfo(&clientbuf);
1083 initStringInfo(&logbuf);
1084 initStringInfo(&locktagbuf);
1085
1086 /* Generate the "waits for" lines sent to the client */
1087 for (i = 0; i < nDeadlockDetails; i++)
1088 {
1090 int nextpid;
1091
1092 /* The last proc waits for the first one... */
1093 if (i < nDeadlockDetails - 1)
1094 nextpid = info[1].pid;
1095 else
1096 nextpid = deadlockDetails[0].pid;
1097
1098 /* reset locktagbuf to hold next object description */
1099 resetStringInfo(&locktagbuf);
1100
1101 DescribeLockTag(&locktagbuf, &info->locktag);
1102
1103 if (i > 0)
1104 appendStringInfoChar(&clientbuf, '\n');
1105
1106 appendStringInfo(&clientbuf,
1107 _("Process %d waits for %s on %s; blocked by process %d."),
1108 info->pid,
1110 info->lockmode),
1111 locktagbuf.data,
1112 nextpid);
1113 }
1114
1115 /* Duplicate all the above for the server ... */
1116 appendBinaryStringInfo(&logbuf, clientbuf.data, clientbuf.len);
1117
1118 /* ... and add info about query strings */
1119 for (i = 0; i < nDeadlockDetails; i++)
1120 {
1122
1123 appendStringInfoChar(&logbuf, '\n');
1124
1125 appendStringInfo(&logbuf,
1126 _("Process %d: %s"),
1127 info->pid,
1129 }
1130
1132
1133 ereport(ERROR,
1135 errmsg("deadlock detected"),
1136 errdetail_internal("%s", clientbuf.data),
1137 errdetail_log("%s", logbuf.data),
1138 errhint("See server log for query details.")));
1139}
const char * pgstat_get_backend_current_activity(int pid, bool checkUser)
static int nDeadlockDetails
Definition: deadlock.c:126
static DEADLOCK_INFO * deadlockDetails
Definition: deadlock.c:125
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1231
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errdetail_log(const char *fmt,...)
Definition: elog.c:1252
#define _(x)
Definition: elog.c:91
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition: lmgr.c:1243
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:4223
#define ERRCODE_T_R_DEADLOCK_DETECTED
Definition: pgbench.c:78
void pgstat_report_deadlock(void)
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:126
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:242
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
LOCKTAG locktag
Definition: deadlock.c:74
LOCKMODE lockmode
Definition: deadlock.c:75
uint8 locktag_lockmethodid
Definition: lock.h:172

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

Referenced by LockAcquireExtended().

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 622 of file lock.c.

623{
624 LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
625
626 if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
627 return true;
628
629 return false;
630}
static const LockMethod LockMethods[]
Definition: lock.c:150
#define LOCKBIT_ON(lockmode)
Definition: lock.h:85
const LOCKMASK * conflictTab
Definition: lock.h:112

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, LOCKBIT_ON, and LockMethods.

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

◆ GetAwaitedLock()

LOCALLOCK * GetAwaitedLock ( void  )

Definition at line 1897 of file lock.c.

1898{
1899 return awaitedLock;
1900}
static LOCALLOCK * awaitedLock
Definition: lock.c:328

References awaitedLock.

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

◆ GetBlockerStatusData()

BlockedProcsData * GetBlockerStatusData ( int  blocked_pid)

Definition at line 3966 of file lock.c.

3967{
3969 PGPROC *proc;
3970 int i;
3971
3973
3974 /*
3975 * Guess how much space we'll need, and preallocate. Most of the time
3976 * this will avoid needing to do repalloc while holding the LWLocks. (We
3977 * assume, but check with an Assert, that MaxBackends is enough entries
3978 * for the procs[] array; the other two could need enlargement, though.)
3979 */
3980 data->nprocs = data->nlocks = data->npids = 0;
3981 data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3982 data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
3983 data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3984 data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3985
3986 /*
3987 * In order to search the ProcArray for blocked_pid and assume that that
3988 * entry won't immediately disappear under us, we must hold ProcArrayLock.
3989 * In addition, to examine the lock grouping fields of any other backend,
3990 * we must hold all the hash partition locks. (Only one of those locks is
3991 * actually relevant for any one lock group, but we can't know which one
3992 * ahead of time.) It's fairly annoying to hold all those locks
3993 * throughout this, but it's no worse than GetLockStatusData(), and it
3994 * does have the advantage that we're guaranteed to return a
3995 * self-consistent instantaneous state.
3996 */
3997 LWLockAcquire(ProcArrayLock, LW_SHARED);
3998
3999 proc = BackendPidGetProcWithLock(blocked_pid);
4000
4001 /* Nothing to do if it's gone */
4002 if (proc != NULL)
4003 {
4004 /*
4005 * Acquire lock on the entire shared lock data structure. See notes
4006 * in GetLockStatusData().
4007 */
4008 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
4010
4011 if (proc->lockGroupLeader == NULL)
4012 {
4013 /* Easy case, proc is not a lock group member */
4015 }
4016 else
4017 {
4018 /* Examine all procs in proc's lock group */
4019 dlist_iter iter;
4020
4022 {
4023 PGPROC *memberProc;
4024
4025 memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
4027 }
4028 }
4029
4030 /*
4031 * And release locks. See notes in GetLockStatusData().
4032 */
4033 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
4035
4036 Assert(data->nprocs <= data->maxprocs);
4037 }
4038
4039 LWLockRelease(ProcArrayLock);
4040
4041 return data;
4042}
int MaxBackends
Definition: globals.c:147
#define dlist_foreach(iter, lhead)
Definition: ilist.h:623
#define dlist_container(type, membername, ptr)
Definition: ilist.h:593
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition: lock.c:4046
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:530
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1182
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1902
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:97
@ LW_SHARED
Definition: lwlock.h:115
void * palloc(Size size)
Definition: mcxt.c:1945
const void * data
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3219
dlist_head lockGroupMembers
Definition: proc.h:314
PGPROC * lockGroupLeader
Definition: proc.h:313
dlist_node * cur
Definition: ilist.h:179

References Assert(), BackendPidGetProcWithLock(), dlist_iter::cur, data, dlist_container, dlist_foreach, GetSingleProcBlockerStatusData(), i, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LockHashPartitionLockByIndex, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaxBackends, NUM_LOCK_PARTITIONS, and palloc().

Referenced by pg_blocking_pids().

◆ GetBlockingAutoVacuumPgproc()

PGPROC * GetBlockingAutoVacuumPgproc ( void  )

Definition at line 290 of file deadlock.c.

291{
292 PGPROC *ptr;
293
296
297 return ptr;
298}

References blocking_autovacuum_proc.

Referenced by ProcSleep().

◆ GetLockConflicts()

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

Definition at line 3037 of file lock.c.

3038{
3039 static VirtualTransactionId *vxids;
3040 LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
3041 LockMethod lockMethodTable;
3042 LOCK *lock;
3043 LOCKMASK conflictMask;
3044 dlist_iter proclock_iter;
3045 PROCLOCK *proclock;
3046 uint32 hashcode;
3047 LWLock *partitionLock;
3048 int count = 0;
3049 int fast_count = 0;
3050
3051 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
3052 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
3053 lockMethodTable = LockMethods[lockmethodid];
3054 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
3055 elog(ERROR, "unrecognized lock mode: %d", lockmode);
3056
3057 /*
3058 * Allocate memory to store results, and fill with InvalidVXID. We only
3059 * need enough space for MaxBackends + max_prepared_xacts + a terminator.
3060 * InHotStandby allocate once in TopMemoryContext.
3061 */
3062 if (InHotStandby)
3063 {
3064 if (vxids == NULL)
3065 vxids = (VirtualTransactionId *)
3067 sizeof(VirtualTransactionId) *
3069 }
3070 else
3071 vxids = (VirtualTransactionId *)
3074
3075 /* Compute hash code and partition lock, and look up conflicting modes. */
3076 hashcode = LockTagHashCode(locktag);
3077 partitionLock = LockHashPartitionLock(hashcode);
3078 conflictMask = lockMethodTable->conflictTab[lockmode];
3079
3080 /*
3081 * Fast path locks might not have been entered in the primary lock table.
3082 * If the lock we're dealing with could conflict with such a lock, we must
3083 * examine each backend's fast-path array for conflicts.
3084 */
3085 if (ConflictsWithRelationFastPath(locktag, lockmode))
3086 {
3087 int i;
3088 Oid relid = locktag->locktag_field2;
3090
3091 /* fast-path group the lock belongs to */
3092 uint32 group = FAST_PATH_REL_GROUP(relid);
3093
3094 /*
3095 * Iterate over relevant PGPROCs. Anything held by a prepared
3096 * transaction will have been transferred to the primary lock table,
3097 * so we need not worry about those. This is all a bit fuzzy, because
3098 * new locks could be taken after we've visited a particular
3099 * partition, but the callers had better be prepared to deal with that
3100 * anyway, since the locks could equally well be taken between the
3101 * time we return the value and the time the caller does something
3102 * with it.
3103 */
3104 for (i = 0; i < ProcGlobal->allProcCount; i++)
3105 {
3106 PGPROC *proc = &ProcGlobal->allProcs[i];
3107 uint32 j;
3108
3109 /* A backend never blocks itself */
3110 if (proc == MyProc)
3111 continue;
3112
3114
3115 /*
3116 * If the target backend isn't referencing the same database as
3117 * the lock, then we needn't examine the individual relation IDs
3118 * at all; none of them can be relevant.
3119 *
3120 * See FastPathTransferRelationLocks() for discussion of why we do
3121 * this test after acquiring the lock.
3122 *
3123 * Also skip groups without any registered fast-path locks.
3124 */
3125 if (proc->databaseId != locktag->locktag_field1 ||
3126 proc->fpLockBits[group] == 0)
3127 {
3128 LWLockRelease(&proc->fpInfoLock);
3129 continue;
3130 }
3131
3132 for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++)
3133 {
3134 uint32 lockmask;
3135
3136 /* index into the whole per-backend array */
3137 uint32 f = FAST_PATH_SLOT(group, j);
3138
3139 /* Look for an allocated slot matching the given relid. */
3140 if (relid != proc->fpRelId[f])
3141 continue;
3142 lockmask = FAST_PATH_GET_BITS(proc, f);
3143 if (!lockmask)
3144 continue;
3145 lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
3146
3147 /*
3148 * There can only be one entry per relation, so if we found it
3149 * and it doesn't conflict, we can skip the rest of the slots.
3150 */
3151 if ((lockmask & conflictMask) == 0)
3152 break;
3153
3154 /* Conflict! */
3155 GET_VXID_FROM_PGPROC(vxid, *proc);
3156
3158 vxids[count++] = vxid;
3159 /* else, xact already committed or aborted */
3160
3161 /* No need to examine remaining slots. */
3162 break;
3163 }
3164
3165 LWLockRelease(&proc->fpInfoLock);
3166 }
3167 }
3168
3169 /* Remember how many fast-path conflicts we found. */
3170 fast_count = count;
3171
3172 /*
3173 * Look up the lock object matching the tag.
3174 */
3175 LWLockAcquire(partitionLock, LW_SHARED);
3176
3178 locktag,
3179 hashcode,
3180 HASH_FIND,
3181 NULL);
3182 if (!lock)
3183 {
3184 /*
3185 * If the lock object doesn't exist, there is nothing holding a lock
3186 * on this lockable object.
3187 */
3188 LWLockRelease(partitionLock);
3189 vxids[count].procNumber = INVALID_PROC_NUMBER;
3191 if (countp)
3192 *countp = count;
3193 return vxids;
3194 }
3195
3196 /*
3197 * Examine each existing holder (or awaiter) of the lock.
3198 */
3199 dlist_foreach(proclock_iter, &lock->procLocks)
3200 {
3201 proclock = dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
3202
3203 if (conflictMask & proclock->holdMask)
3204 {
3205 PGPROC *proc = proclock->tag.myProc;
3206
3207 /* A backend never blocks itself */
3208 if (proc != MyProc)
3209 {
3211
3212 GET_VXID_FROM_PGPROC(vxid, *proc);
3213
3215 {
3216 int i;
3217
3218 /* Avoid duplicate entries. */
3219 for (i = 0; i < fast_count; ++i)
3220 if (VirtualTransactionIdEquals(vxids[i], vxid))
3221 break;
3222 if (i >= fast_count)
3223 vxids[count++] = vxid;
3224 }
3225 /* else, xact already committed or aborted */
3226 }
3227 }
3228 }
3229
3230 LWLockRelease(partitionLock);
3231
3232 if (count > MaxBackends + max_prepared_xacts) /* should never happen */
3233 elog(PANIC, "too many conflicting locks found");
3234
3235 vxids[count].procNumber = INVALID_PROC_NUMBER;
3237 if (countp)
3238 *countp = count;
3239 return vxids;
3240}
#define lengthof(array)
Definition: c.h:759
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:969
#define PANIC
Definition: elog.h:42
@ HASH_FIND
Definition: hsearch.h:113
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:242
#define FAST_PATH_REL_GROUP(rel)
Definition: lock.c:217
#define FAST_PATH_SLOT(group, index)
Definition: lock.c:224
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:273
static HTAB * LockMethodLockHash
Definition: lock.c:321
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:245
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:556
uint16 LOCKMETHODID
Definition: lock.h:123
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:68
#define LockHashPartitionLock(hashcode)
Definition: lock.h:527
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition: lock.h:78
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:72
int LOCKMASK
Definition: lockdefs.h:25
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1260
void * palloc0(Size size)
Definition: mcxt.c:1975
MemoryContext TopMemoryContext
Definition: mcxt.c:165
unsigned int Oid
Definition: postgres_ext.h:30
#define FP_LOCK_SLOTS_PER_GROUP
Definition: proc.h:92
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:79
uint32 locktag_field1
Definition: lock.h:167
uint32 locktag_field2
Definition: lock.h:168
dlist_head procLocks
Definition: lock.h:317
Definition: lwlock.h:42
int numLockModes
Definition: lock.h:111
LWLock fpInfoLock
Definition: proc.h:302
Oid * fpRelId
Definition: proc.h:304
Oid databaseId
Definition: proc.h:216
uint64 * fpLockBits
Definition: proc.h:303
PGPROC * myProc
Definition: lock.h:367
Definition: lock.h:371
LOCKMASK holdMask
Definition: lock.h:377
PGPROC * allProcs
Definition: proc.h:380
uint32 allProcCount
Definition: proc.h:398
LocalTransactionId localTransactionId
Definition: lock.h:63
ProcNumber procNumber
Definition: lock.h:62
int max_prepared_xacts
Definition: twophase.c:115
#define InHotStandby
Definition: xlogutils.h:60

References PROC_HDR::allProcCount, PROC_HDR::allProcs, ConflictsWithRelationFastPath, LockMethodData::conflictTab, dlist_iter::cur, PGPROC::databaseId, dlist_container, dlist_foreach, elog, ERROR, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, FAST_PATH_REL_GROUP, FAST_PATH_SLOT, FP_LOCK_SLOTS_PER_GROUP, PGPROC::fpInfoLock, PGPROC::fpLockBits, PGPROC::fpRelId, GET_VXID_FROM_PGPROC, HASH_FIND, hash_search_with_hash_value(), PROCLOCK::holdMask, i, InHotStandby, INVALID_PROC_NUMBER, InvalidLocalTransactionId, j, lengthof, VirtualTransactionId::localTransactionId, LockHashPartitionLock, LockMethodLockHash, LockMethods, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LockTagHashCode(), LW_SHARED, LWLockAcquire(), LWLockRelease(), max_prepared_xacts, MaxBackends, MemoryContextAlloc(), MyProc, PROCLOCKTAG::myProc, LockMethodData::numLockModes, palloc0(), PANIC, ProcGlobal, LOCK::procLocks, VirtualTransactionId::procNumber, PROCLOCK::tag, TopMemoryContext, VirtualTransactionIdEquals, and VirtualTransactionIdIsValid.

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

◆ GetLockmodeName()

const char * GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

Definition at line 4223 of file lock.c.

4224{
4225 Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
4226 Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
4227 return LockMethods[lockmethodid]->lockModeNames[mode];
4228}
static PgChecksumMode mode
Definition: pg_checksums.c:55
const char *const * lockModeNames
Definition: lock.h:113

References Assert(), lengthof, LockMethods, LockMethodData::lockModeNames, and mode.

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

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)

Definition at line 526 of file lock.c.

527{
528 LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
529
530 Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
531 return LockMethods[lockmethodid];
532}
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:325

References Assert(), lengthof, LOCK_LOCKMETHOD, and LockMethods.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

◆ GetLockStatusData()

LockData * GetLockStatusData ( void  )

Definition at line 3763 of file lock.c.

3764{
3765 LockData *data;
3766 PROCLOCK *proclock;
3767 HASH_SEQ_STATUS seqstat;
3768 int els;
3769 int el;
3770 int i;
3771
3772 data = (LockData *) palloc(sizeof(LockData));
3773
3774 /* Guess how much space we'll need. */
3775 els = MaxBackends;
3776 el = 0;
3777 data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3778
3779 /*
3780 * First, we iterate through the per-backend fast-path arrays, locking
3781 * them one at a time. This might produce an inconsistent picture of the
3782 * system state, but taking all of those LWLocks at the same time seems
3783 * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3784 * matter too much, because none of these locks can be involved in lock
3785 * conflicts anyway - anything that might must be present in the main lock
3786 * table. (For the same reason, we don't sweat about making leaderPid
3787 * completely valid. We cannot safely dereference another backend's
3788 * lockGroupLeader field without holding all lock partition locks, and
3789 * it's not worth that.)
3790 */
3791 for (i = 0; i < ProcGlobal->allProcCount; ++i)
3792 {
3793 PGPROC *proc = &ProcGlobal->allProcs[i];
3794
3795 /* Skip backends with pid=0, as they don't hold fast-path locks */
3796 if (proc->pid == 0)
3797 continue;
3798
3800
3801 for (uint32 g = 0; g < FastPathLockGroupsPerBackend; g++)
3802 {
3803 /* Skip groups without registered fast-path locks */
3804 if (proc->fpLockBits[g] == 0)
3805 continue;
3806
3807 for (int j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++)
3808 {
3809 LockInstanceData *instance;
3810 uint32 f = FAST_PATH_SLOT(g, j);
3811 uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3812
3813 /* Skip unallocated slots */
3814 if (!lockbits)
3815 continue;
3816
3817 if (el >= els)
3818 {
3819 els += MaxBackends;
3820 data->locks = (LockInstanceData *)
3821 repalloc(data->locks, sizeof(LockInstanceData) * els);
3822 }
3823
3824 instance = &data->locks[el];
3825 SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3826 proc->fpRelId[f]);
3827 instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3828 instance->waitLockMode = NoLock;
3829 instance->vxid.procNumber = proc->vxid.procNumber;
3830 instance->vxid.localTransactionId = proc->vxid.lxid;
3831 instance->pid = proc->pid;
3832 instance->leaderPid = proc->pid;
3833 instance->fastpath = true;
3834
3835 /*
3836 * Successfully taking fast path lock means there were no
3837 * conflicting locks.
3838 */
3839 instance->waitStart = 0;
3840
3841 el++;
3842 }
3843 }
3844
3845 if (proc->fpVXIDLock)
3846 {
3848 LockInstanceData *instance;
3849
3850 if (el >= els)
3851 {
3852 els += MaxBackends;
3853 data->locks = (LockInstanceData *)
3854 repalloc(data->locks, sizeof(LockInstanceData) * els);
3855 }
3856
3857 vxid.procNumber = proc->vxid.procNumber;
3859
3860 instance = &data->locks[el];
3861 SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3862 instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3863 instance->waitLockMode = NoLock;
3864 instance->vxid.procNumber = proc->vxid.procNumber;
3865 instance->vxid.localTransactionId = proc->vxid.lxid;
3866 instance->pid = proc->pid;
3867 instance->leaderPid = proc->pid;
3868 instance->fastpath = true;
3869 instance->waitStart = 0;
3870
3871 el++;
3872 }
3873
3874 LWLockRelease(&proc->fpInfoLock);
3875 }
3876
3877 /*
3878 * Next, acquire lock on the entire shared lock data structure. We do
3879 * this so that, at least for locks in the primary lock table, the state
3880 * will be self-consistent.
3881 *
3882 * Since this is a read-only operation, we take shared instead of
3883 * exclusive lock. There's not a whole lot of point to this, because all
3884 * the normal operations require exclusive lock, but it doesn't hurt
3885 * anything either. It will at least allow two backends to do
3886 * GetLockStatusData in parallel.
3887 *
3888 * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3889 */
3890 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3892
3893 /* Now we can safely count the number of proclocks */
3895 if (data->nelements > els)
3896 {
3897 els = data->nelements;
3898 data->locks = (LockInstanceData *)
3899 repalloc(data->locks, sizeof(LockInstanceData) * els);
3900 }
3901
3902 /* Now scan the tables to copy the data */
3904
3905 while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3906 {
3907 PGPROC *proc = proclock->tag.myProc;
3908 LOCK *lock = proclock->tag.myLock;
3909 LockInstanceData *instance = &data->locks[el];
3910
3911 memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3912 instance->holdMask = proclock->holdMask;
3913 if (proc->waitLock == proclock->tag.myLock)
3914 instance->waitLockMode = proc->waitLockMode;
3915 else
3916 instance->waitLockMode = NoLock;
3917 instance->vxid.procNumber = proc->vxid.procNumber;
3918 instance->vxid.localTransactionId = proc->vxid.lxid;
3919 instance->pid = proc->pid;
3920 instance->leaderPid = proclock->groupLeader->pid;
3921 instance->fastpath = false;
3922 instance->waitStart = (TimestampTz) pg_atomic_read_u64(&proc->waitStart);
3923
3924 el++;
3925 }
3926
3927 /*
3928 * And release locks. We do this in reverse order for two reasons: (1)
3929 * Anyone else who needs more than one of the locks will be trying to lock
3930 * them in increasing order; we don't want to release the other process
3931 * until it can get all the locks it needs. (2) This avoids O(N^2)
3932 * behavior inside LWLockRelease.
3933 */
3934 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3936
3937 Assert(el == data->nelements);
3938
3939 return data;
3940}
static uint64 pg_atomic_read_u64(volatile pg_atomic_uint64 *ptr)
Definition: atomics.h:467
int64 TimestampTz
Definition: timestamp.h:39
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1342
int FastPathLockGroupsPerBackend
Definition: lock.c:202
static HTAB * LockMethodProcLockHash
Definition: lock.c:322
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition: lock.h:236
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:182
#define NoLock
Definition: lockdefs.h:34
#define ExclusiveLock
Definition: lockdefs.h:42
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:2172
LOCKTAG tag
Definition: lock.h:312
Definition: lock.h:467
LOCKMASK holdMask
Definition: lock.h:456
LOCKMODE waitLockMode
Definition: lock.h:457
bool fastpath
Definition: lock.h:463
LOCKTAG locktag
Definition: lock.h:455
TimestampTz waitStart
Definition: lock.h:459
int leaderPid
Definition: lock.h:462
VirtualTransactionId vxid
Definition: lock.h:458
struct PGPROC::@127 vxid
LocalTransactionId lxid
Definition: proc.h:209
pg_atomic_uint64 waitStart
Definition: proc.h:246
bool fpVXIDLock
Definition: proc.h:305
ProcNumber procNumber
Definition: proc.h:204
int pid
Definition: proc.h:191
LOCK * waitLock
Definition: proc.h:241
LOCKMODE waitLockMode
Definition: proc.h:243
LocalTransactionId fpLocalTransactionId
Definition: proc.h:306
PGPROC * groupLeader
Definition: lock.h:376

References PROC_HDR::allProcCount, PROC_HDR::allProcs, Assert(), data, PGPROC::databaseId, ExclusiveLock, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, FAST_PATH_SLOT, LockInstanceData::fastpath, FastPathLockGroupsPerBackend, FP_LOCK_SLOTS_PER_GROUP, PGPROC::fpInfoLock, PGPROC::fpLocalTransactionId, PGPROC::fpLockBits, PGPROC::fpRelId, PGPROC::fpVXIDLock, PROCLOCK::groupLeader, hash_get_num_entries(), hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, LockInstanceData::holdMask, i, j, LockInstanceData::leaderPid, VirtualTransactionId::localTransactionId, LOCKBIT_ON, LockHashPartitionLockByIndex, LockMethodProcLockHash, LockInstanceData::locktag, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, MaxBackends, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, NoLock, NUM_LOCK_PARTITIONS, palloc(), pg_atomic_read_u64(), LockInstanceData::pid, PGPROC::pid, ProcGlobal, VirtualTransactionId::procNumber, PGPROC::procNumber, repalloc(), SET_LOCKTAG_RELATION, SET_LOCKTAG_VIRTUALTRANSACTION, LOCK::tag, PROCLOCK::tag, LockInstanceData::vxid, PGPROC::vxid, PGPROC::waitLock, LockInstanceData::waitLockMode, PGPROC::waitLockMode, LockInstanceData::waitStart, and PGPROC::waitStart.

Referenced by pg_lock_status().

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 538 of file lock.c.

539{
540 LOCKMETHODID lockmethodid = (LOCKMETHODID) locktag->locktag_lockmethodid;
541
542 Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
543 return LockMethods[lockmethodid];
544}

References Assert(), lengthof, LockMethods, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

◆ GetRunningTransactionLocks()

xl_standby_lock * GetRunningTransactionLocks ( int *  nlocks)

Definition at line 4141 of file lock.c.

4142{
4143 xl_standby_lock *accessExclusiveLocks;
4144 PROCLOCK *proclock;
4145 HASH_SEQ_STATUS seqstat;
4146 int i;
4147 int index;
4148 int els;
4149
4150 /*
4151 * Acquire lock on the entire shared lock data structure.
4152 *
4153 * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
4154 */
4155 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
4157
4158 /* Now we can safely count the number of proclocks */
4160
4161 /*
4162 * Allocating enough space for all locks in the lock table is overkill,
4163 * but it's more convenient and faster than having to enlarge the array.
4164 */
4165 accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
4166
4167 /* Now scan the tables to copy the data */
4169
4170 /*
4171 * If lock is a currently granted AccessExclusiveLock then it will have
4172 * just one proclock holder, so locks are never accessed twice in this
4173 * particular case. Don't copy this code for use elsewhere because in the
4174 * general case this will give you duplicate locks when looking at
4175 * non-exclusive lock types.
4176 */
4177 index = 0;
4178 while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
4179 {
4180 /* make sure this definition matches the one used in LockAcquire */
4181 if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
4183 {
4184 PGPROC *proc = proclock->tag.myProc;
4185 LOCK *lock = proclock->tag.myLock;
4186 TransactionId xid = proc->xid;
4187
4188 /*
4189 * Don't record locks for transactions if we know they have
4190 * already issued their WAL record for commit but not yet released
4191 * lock. It is still possible that we see locks held by already
4192 * complete transactions, if they haven't yet zeroed their xids.
4193 */
4194 if (!TransactionIdIsValid(xid))
4195 continue;
4196
4197 accessExclusiveLocks[index].xid = xid;
4198 accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
4199 accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
4200
4201 index++;
4202 }
4203 }
4204
4205 Assert(index <= els);
4206
4207 /*
4208 * And release locks. We do this in reverse order for two reasons: (1)
4209 * Anyone else who needs more than one of the locks will be trying to lock
4210 * them in increasing order; we don't want to release the other process
4211 * until it can get all the locks it needs. (2) This avoids O(N^2)
4212 * behavior inside LWLockRelease.
4213 */
4214 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
4216
4217 *nlocks = index;
4218 return accessExclusiveLocks;
4219}
uint32 TransactionId
Definition: c.h:623
#define AccessExclusiveLock
Definition: lockdefs.h:43
TransactionId xid
Definition: proc.h:181
Definition: type.h:96
TransactionId xid
Definition: lockdefs.h:53
#define TransactionIdIsValid(xid)
Definition: transam.h:41

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

Referenced by LogStandbySnapshot().

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1888 of file lock.c.

1889{
1891}
static ResourceOwner awaitedOwner
Definition: lock.c:329
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1791

References awaitedLock, awaitedOwner, and GrantLockLocal().

Referenced by LockErrorCleanup().

◆ GrantLock()

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

Definition at line 1657 of file lock.c.

1658{
1659 lock->nGranted++;
1660 lock->granted[lockmode]++;
1661 lock->grantMask |= LOCKBIT_ON(lockmode);
1662 if (lock->granted[lockmode] == lock->requested[lockmode])
1663 lock->waitMask &= LOCKBIT_OFF(lockmode);
1664 proclock->holdMask |= LOCKBIT_ON(lockmode);
1665 LOCK_PRINT("GrantLock", lock, lockmode);
1666 Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1667 Assert(lock->nGranted <= lock->nRequested);
1668}
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:405
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:86
int nRequested
Definition: lock.h:320
int requested[MAX_LOCKMODES]
Definition: lock.h:319
int granted[MAX_LOCKMODES]
Definition: lock.h:321
LOCKMASK grantMask
Definition: lock.h:315
LOCKMASK waitMask
Definition: lock.h:316
int nGranted
Definition: lock.h:322

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

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

◆ InitDeadLockChecking()

void InitDeadLockChecking ( void  )

Definition at line 144 of file deadlock.c.

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

References afterConstraints, beforeConstraints, curConstraints, deadlockDetails, MAX_BACKENDS_BITS, MaxBackends, maxCurConstraints, maxPossibleConstraints, MemoryContextSwitchTo(), palloc(), possibleConstraints, StaticAssertStmt, TopMemoryContext, topoProcs, visitedProcs, waitOrderProcs, and waitOrders.

Referenced by InitProcess().

◆ InitLockManagerAccess()

void InitLockManagerAccess ( void  )

Definition at line 504 of file lock.c.

505{
506 /*
507 * Allocate non-shared hash table for LOCALLOCK structs. This stores lock
508 * counts and resource owner information.
509 */
510 HASHCTL info;
511
512 info.keysize = sizeof(LOCALLOCKTAG);
513 info.entrysize = sizeof(LOCALLOCK);
514
515 LockMethodLocalHash = hash_create("LOCALLOCK hash",
516 16,
517 &info,
519}
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
struct LOCALLOCK LOCALLOCK
struct LOCALLOCKTAG LOCALLOCKTAG
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASHCTL::keysize, and LockMethodLocalHash.

Referenced by BaseInit().

◆ lock_twophase_postabort()

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

Definition at line 4566 of file lock.c.

4568{
4569 lock_twophase_postcommit(xid, info, recdata, len);
4570}
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
Definition: lock.c:4540
const void size_t len

References len, and lock_twophase_postcommit().

◆ lock_twophase_postcommit()

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

Definition at line 4540 of file lock.c.

4542{
4543 TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4544 PGPROC *proc = TwoPhaseGetDummyProc(xid, true);
4545 LOCKTAG *locktag;
4546 LOCKMETHODID lockmethodid;
4547 LockMethod lockMethodTable;
4548
4549 Assert(len == sizeof(TwoPhaseLockRecord));
4550 locktag = &rec->locktag;
4551 lockmethodid = locktag->locktag_lockmethodid;
4552
4553 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4554 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4555 lockMethodTable = LockMethods[lockmethodid];
4556
4557 LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4558}
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3254
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:918

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

Referenced by lock_twophase_postabort().

◆ lock_twophase_recover()

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

Definition at line 4327 of file lock.c.

4329{
4330 TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4331 PGPROC *proc = TwoPhaseGetDummyProc(xid, false);
4332 LOCKTAG *locktag;
4333 LOCKMODE lockmode;
4334 LOCKMETHODID lockmethodid;
4335 LOCK *lock;
4336 PROCLOCK *proclock;
4337 PROCLOCKTAG proclocktag;
4338 bool found;
4339 uint32 hashcode;
4340 uint32 proclock_hashcode;
4341 int partition;
4342 LWLock *partitionLock;
4343 LockMethod lockMethodTable;
4344
4345 Assert(len == sizeof(TwoPhaseLockRecord));
4346 locktag = &rec->locktag;
4347 lockmode = rec->lockmode;
4348 lockmethodid = locktag->locktag_lockmethodid;
4349
4350 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4351 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4352 lockMethodTable = LockMethods[lockmethodid];
4353
4354 hashcode = LockTagHashCode(locktag);
4355 partition = LockHashPartition(hashcode);
4356 partitionLock = LockHashPartitionLock(hashcode);
4357
4358 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4359
4360 /*
4361 * Find or create a lock with this tag.
4362 */
4364 locktag,
4365 hashcode,
4367 &found);
4368 if (!lock)
4369 {
4370 LWLockRelease(partitionLock);
4371 ereport(ERROR,
4372 (errcode(ERRCODE_OUT_OF_MEMORY),
4373 errmsg("out of shared memory"),
4374 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4375 }
4376
4377 /*
4378 * if it's a new lock object, initialize it
4379 */
4380 if (!found)
4381 {
4382 lock->grantMask = 0;
4383 lock->waitMask = 0;
4384 dlist_init(&lock->procLocks);
4385 dclist_init(&lock->waitProcs);
4386 lock->nRequested = 0;
4387 lock->nGranted = 0;
4388 MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4389 MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4390 LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4391 }
4392 else
4393 {
4394 LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4395 Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4396 Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4397 Assert(lock->nGranted <= lock->nRequested);
4398 }
4399
4400 /*
4401 * Create the hash key for the proclock table.
4402 */
4403 proclocktag.myLock = lock;
4404 proclocktag.myProc = proc;
4405
4406 proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4407
4408 /*
4409 * Find or create a proclock entry with this tag
4410 */
4412 &proclocktag,
4413 proclock_hashcode,
4415 &found);
4416 if (!proclock)
4417 {
4418 /* Oops, not enough shmem for the proclock */
4419 if (lock->nRequested == 0)
4420 {
4421 /*
4422 * There are no other requestors of this lock, so garbage-collect
4423 * the lock object. We *must* do this to avoid a permanent leak
4424 * of shared memory, because there won't be anything to cause
4425 * anyone to release the lock object later.
4426 */
4429 &(lock->tag),
4430 hashcode,
4432 NULL))
4433 elog(PANIC, "lock table corrupted");
4434 }
4435 LWLockRelease(partitionLock);
4436 ereport(ERROR,
4437 (errcode(ERRCODE_OUT_OF_MEMORY),
4438 errmsg("out of shared memory"),
4439 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4440 }
4441
4442 /*
4443 * If new, initialize the new entry
4444 */
4445 if (!found)
4446 {
4447 Assert(proc->lockGroupLeader == NULL);
4448 proclock->groupLeader = proc;
4449 proclock->holdMask = 0;
4450 proclock->releaseMask = 0;
4451 /* Add proclock to appropriate lists */
4452 dlist_push_tail(&lock->procLocks, &proclock->lockLink);
4453 dlist_push_tail(&proc->myProcLocks[partition],
4454 &proclock->procLink);
4455 PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4456 }
4457 else
4458 {
4459 PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4460 Assert((proclock->holdMask & ~lock->grantMask) == 0);
4461 }
4462
4463 /*
4464 * lock->nRequested and lock->requested[] count the total number of
4465 * requests, whether granted or waiting, so increment those immediately.
4466 */
4467 lock->nRequested++;
4468 lock->requested[lockmode]++;
4469 Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4470
4471 /*
4472 * We shouldn't already hold the desired lock.
4473 */
4474 if (proclock->holdMask & LOCKBIT_ON(lockmode))
4475 elog(ERROR, "lock %s on object %u/%u/%u is already held",
4476 lockMethodTable->lockModeNames[lockmode],
4477 lock->tag.locktag_field1, lock->tag.locktag_field2,
4478 lock->tag.locktag_field3);
4479
4480 /*
4481 * We ignore any possible conflicts and just grant ourselves the lock. Not
4482 * only because we don't bother, but also to avoid deadlocks when
4483 * switching from standby to normal mode. See function comment.
4484 */
4485 GrantLock(lock, proclock, lockmode);
4486
4487 /*
4488 * Bump strong lock count, to make sure any fast-path lock requests won't
4489 * be granted without consulting the primary lock table.
4490 */
4491 if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4492 {
4493 uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4494
4496 FastPathStrongRelationLocks->count[fasthashcode]++;
4498 }
4499
4500 LWLockRelease(partitionLock);
4501}
#define MemSet(start, val, len)
Definition: c.h:991
@ HASH_REMOVE
Definition: hsearch.h:115
@ HASH_ENTER_NULL
Definition: hsearch.h:116
static void dlist_init(dlist_head *head)
Definition: ilist.h:314
static bool dlist_is_empty(const dlist_head *head)
Definition: ilist.h:336
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition: ilist.h:364
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:604
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1657
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:406
#define MAX_LOCKMODES
Definition: lock.h:83
#define LockHashPartition(hashcode)
Definition: lock.h:525
int LOCKMODE
Definition: lockdefs.h:26
@ LW_EXCLUSIVE
Definition: lwlock.h:114
uint32 locktag_field3
Definition: lock.h:169
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:270
dlist_node lockLink
Definition: lock.h:379
LOCKMASK releaseMask
Definition: lock.h:378
dlist_node procLink
Definition: lock.h:380

References Assert(), ConflictsWithRelationFastPath, FastPathStrongRelationLockData::count, dclist_init(), dlist_init(), dlist_is_empty(), dlist_push_tail(), elog, ereport, errcode(), errhint(), errmsg(), ERROR, FastPathStrongLockHashPartition, FastPathStrongRelationLocks, LOCK::granted, GrantLock(), LOCK::grantMask, PROCLOCK::groupLeader, HASH_ENTER_NULL, HASH_REMOVE, hash_search_with_hash_value(), PROCLOCK::holdMask, len, lengthof, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartition, LockHashPartitionLock, PROCLOCK::lockLink, LockMethodLockHash, LockMethodProcLockHash, LockMethods, 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, PROCLOCK::releaseMask, LOCK::requested, SpinLockAcquire, SpinLockRelease, LOCK::tag, TwoPhaseGetDummyProc(), LOCK::waitMask, and LOCK::waitProcs.

◆ lock_twophase_standby_recover()

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

Definition at line 4508 of file lock.c.

4510{
4511 TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4512 LOCKTAG *locktag;
4513 LOCKMODE lockmode;
4514 LOCKMETHODID lockmethodid;
4515
4516 Assert(len == sizeof(TwoPhaseLockRecord));
4517 locktag = &rec->locktag;
4518 lockmode = rec->lockmode;
4519 lockmethodid = locktag->locktag_lockmethodid;
4520
4521 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4522 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4523
4524 if (lockmode == AccessExclusiveLock &&
4525 locktag->locktag_type == LOCKTAG_RELATION)
4526 {
4528 locktag->locktag_field1 /* dboid */ ,
4529 locktag->locktag_field2 /* reloid */ );
4530 }
4531}
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:986

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

◆ LockAcquire()

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

◆ LockAcquireExtended()

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

Definition at line 835 of file lock.c.

842{
843 LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
844 LockMethod lockMethodTable;
845 LOCALLOCKTAG localtag;
846 LOCALLOCK *locallock;
847 LOCK *lock;
848 PROCLOCK *proclock;
849 bool found;
850 ResourceOwner owner;
851 uint32 hashcode;
852 LWLock *partitionLock;
853 bool found_conflict;
854 ProcWaitStatus waitResult;
855 bool log_lock = false;
856
857 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
858 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
859 lockMethodTable = LockMethods[lockmethodid];
860 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
861 elog(ERROR, "unrecognized lock mode: %d", lockmode);
862
863 if (RecoveryInProgress() && !InRecovery &&
864 (locktag->locktag_type == LOCKTAG_OBJECT ||
865 locktag->locktag_type == LOCKTAG_RELATION) &&
866 lockmode > RowExclusiveLock)
868 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
869 errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
870 lockMethodTable->lockModeNames[lockmode]),
871 errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
872
873#ifdef LOCK_DEBUG
874 if (LOCK_DEBUG_ENABLED(locktag))
875 elog(LOG, "LockAcquire: lock [%u,%u] %s",
876 locktag->locktag_field1, locktag->locktag_field2,
877 lockMethodTable->lockModeNames[lockmode]);
878#endif
879
880 /* Identify owner for lock */
881 if (sessionLock)
882 owner = NULL;
883 else
884 owner = CurrentResourceOwner;
885
886 /*
887 * Find or create a LOCALLOCK entry for this lock and lockmode
888 */
889 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
890 localtag.lock = *locktag;
891 localtag.mode = lockmode;
892
894 &localtag,
895 HASH_ENTER, &found);
896
897 /*
898 * if it's a new locallock object, initialize it
899 */
900 if (!found)
901 {
902 locallock->lock = NULL;
903 locallock->proclock = NULL;
904 locallock->hashcode = LockTagHashCode(&(localtag.lock));
905 locallock->nLocks = 0;
906 locallock->holdsStrongLockCount = false;
907 locallock->lockCleared = false;
908 locallock->numLockOwners = 0;
909 locallock->maxLockOwners = 8;
910 locallock->lockOwners = NULL; /* in case next line fails */
911 locallock->lockOwners = (LOCALLOCKOWNER *)
913 locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
914 }
915 else
916 {
917 /* Make sure there will be room to remember the lock */
918 if (locallock->numLockOwners >= locallock->maxLockOwners)
919 {
920 int newsize = locallock->maxLockOwners * 2;
921
922 locallock->lockOwners = (LOCALLOCKOWNER *)
923 repalloc(locallock->lockOwners,
924 newsize * sizeof(LOCALLOCKOWNER));
925 locallock->maxLockOwners = newsize;
926 }
927 }
928 hashcode = locallock->hashcode;
929
930 if (locallockp)
931 *locallockp = locallock;
932
933 /*
934 * If we already hold the lock, we can just increase the count locally.
935 *
936 * If lockCleared is already set, caller need not worry about absorbing
937 * sinval messages related to the lock's object.
938 */
939 if (locallock->nLocks > 0)
940 {
941 GrantLockLocal(locallock, owner);
942 if (locallock->lockCleared)
944 else
946 }
947
948 /*
949 * We don't acquire any other heavyweight lock while holding the relation
950 * extension lock. We do allow to acquire the same relation extension
951 * lock more than once but that case won't reach here.
952 */
953 Assert(!IsRelationExtensionLockHeld);
954
955 /*
956 * Prepare to emit a WAL record if acquisition of this lock needs to be
957 * replayed in a standby server.
958 *
959 * Here we prepare to log; after lock is acquired we'll issue log record.
960 * This arrangement simplifies error recovery in case the preparation step
961 * fails.
962 *
963 * Only AccessExclusiveLocks can conflict with lock types that read-only
964 * transactions can acquire in a standby server. Make sure this definition
965 * matches the one in GetRunningTransactionLocks().
966 */
967 if (lockmode >= AccessExclusiveLock &&
968 locktag->locktag_type == LOCKTAG_RELATION &&
971 {
973 log_lock = true;
974 }
975
976 /*
977 * Attempt to take lock via fast path, if eligible. But if we remember
978 * having filled up the fast path array, we don't attempt to make any
979 * further use of it until we release some locks. It's possible that some
980 * other backend has transferred some of those locks to the shared hash
981 * table, leaving space free, but it's not worth acquiring the LWLock just
982 * to check. It's also possible that we're acquiring a second or third
983 * lock type on a relation we have already locked using the fast-path, but
984 * for now we don't worry about that case either.
985 */
986 if (EligibleForRelationFastPath(locktag, lockmode) &&
988 {
989 uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
990 bool acquired;
991
992 /*
993 * LWLockAcquire acts as a memory sequencing point, so it's safe to
994 * assume that any strong locker whose increment to
995 * FastPathStrongRelationLocks->counts becomes visible after we test
996 * it has yet to begin to transfer fast-path locks.
997 */
999 if (FastPathStrongRelationLocks->count[fasthashcode] != 0)
1000 acquired = false;
1001 else
1002 acquired = FastPathGrantRelationLock(locktag->locktag_field2,
1003 lockmode);
1005 if (acquired)
1006 {
1007 /*
1008 * The locallock might contain stale pointers to some old shared
1009 * objects; we MUST reset these to null before considering the
1010 * lock to be acquired via fast-path.
1011 */
1012 locallock->lock = NULL;
1013 locallock->proclock = NULL;
1014 GrantLockLocal(locallock, owner);
1015 return LOCKACQUIRE_OK;
1016 }
1017 }
1018
1019 /*
1020 * If this lock could potentially have been taken via the fast-path by
1021 * some other backend, we must (temporarily) disable further use of the
1022 * fast-path for this lock tag, and migrate any locks already taken via
1023 * this method to the main lock table.
1024 */
1025 if (ConflictsWithRelationFastPath(locktag, lockmode))
1026 {
1027 uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
1028
1029 BeginStrongLockAcquire(locallock, fasthashcode);
1030 if (!FastPathTransferRelationLocks(lockMethodTable, locktag,
1031 hashcode))
1032 {
1034 if (locallock->nLocks == 0)
1035 RemoveLocalLock(locallock);
1036 if (locallockp)
1037 *locallockp = NULL;
1038 if (reportMemoryError)
1039 ereport(ERROR,
1040 (errcode(ERRCODE_OUT_OF_MEMORY),
1041 errmsg("out of shared memory"),
1042 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
1043 else
1044 return LOCKACQUIRE_NOT_AVAIL;
1045 }
1046 }
1047
1048 /*
1049 * We didn't find the lock in our LOCALLOCK table, and we didn't manage to
1050 * take it via the fast-path, either, so we've got to mess with the shared
1051 * lock table.
1052 */
1053 partitionLock = LockHashPartitionLock(hashcode);
1054
1055 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
1056
1057 /*
1058 * Find or create lock and proclock entries with this tag
1059 *
1060 * Note: if the locallock object already existed, it might have a pointer
1061 * to the lock already ... but we should not assume that that pointer is
1062 * valid, since a lock object with zero hold and request counts can go
1063 * away anytime. So we have to use SetupLockInTable() to recompute the
1064 * lock and proclock pointers, even if they're already set.
1065 */
1066 proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
1067 hashcode, lockmode);
1068 if (!proclock)
1069 {
1071 LWLockRelease(partitionLock);
1072 if (locallock->nLocks == 0)
1073 RemoveLocalLock(locallock);
1074 if (locallockp)
1075 *locallockp = NULL;
1076 if (reportMemoryError)
1077 ereport(ERROR,
1078 (errcode(ERRCODE_OUT_OF_MEMORY),
1079 errmsg("out of shared memory"),
1080 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
1081 else
1082 return LOCKACQUIRE_NOT_AVAIL;
1083 }
1084 locallock->proclock = proclock;
1085 lock = proclock->tag.myLock;
1086 locallock->lock = lock;
1087
1088 /*
1089 * If lock requested conflicts with locks requested by waiters, must join
1090 * wait queue. Otherwise, check for conflict with already-held locks.
1091 * (That's last because most complex check.)
1092 */
1093 if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
1094 found_conflict = true;
1095 else
1096 found_conflict = LockCheckConflicts(lockMethodTable, lockmode,
1097 lock, proclock);
1098
1099 if (!found_conflict)
1100 {
1101 /* No conflict with held or previously requested locks */
1102 GrantLock(lock, proclock, lockmode);
1103 waitResult = PROC_WAIT_STATUS_OK;
1104 }
1105 else
1106 {
1107 /*
1108 * Join the lock's wait queue. We call this even in the dontWait
1109 * case, because JoinWaitQueue() may discover that we can acquire the
1110 * lock immediately after all.
1111 */
1112 waitResult = JoinWaitQueue(locallock, lockMethodTable, dontWait);
1113 }
1114
1115 if (waitResult == PROC_WAIT_STATUS_ERROR)
1116 {
1117 /*
1118 * We're not getting the lock because a deadlock was detected already
1119 * while trying to join the wait queue, or because we would have to
1120 * wait but the caller requested no blocking.
1121 *
1122 * Undo the changes to shared entries before releasing the partition
1123 * lock.
1124 */
1126
1127 if (proclock->holdMask == 0)
1128 {
1129 uint32 proclock_hashcode;
1130
1131 proclock_hashcode = ProcLockHashCode(&proclock->tag,
1132 hashcode);
1133 dlist_delete(&proclock->lockLink);
1134 dlist_delete(&proclock->procLink);
1136 &(proclock->tag),
1137 proclock_hashcode,
1139 NULL))
1140 elog(PANIC, "proclock table corrupted");
1141 }
1142 else
1143 PROCLOCK_PRINT("LockAcquire: did not join wait queue", proclock);
1144 lock->nRequested--;
1145 lock->requested[lockmode]--;
1146 LOCK_PRINT("LockAcquire: did not join wait queue",
1147 lock, lockmode);
1148 Assert((lock->nRequested > 0) &&
1149 (lock->requested[lockmode] >= 0));
1150 Assert(lock->nGranted <= lock->nRequested);
1151 LWLockRelease(partitionLock);
1152 if (locallock->nLocks == 0)
1153 RemoveLocalLock(locallock);
1154
1155 if (dontWait)
1156 {
1157 /*
1158 * Log lock holders and waiters as a detail log message if
1159 * logLockFailure = true and lock acquisition fails with dontWait
1160 * = true
1161 */
1162 if (logLockFailure)
1163 {
1165 lock_waiters_sbuf,
1166 lock_holders_sbuf;
1167 const char *modename;
1168 int lockHoldersNum = 0;
1169
1171 initStringInfo(&lock_waiters_sbuf);
1172 initStringInfo(&lock_holders_sbuf);
1173
1174 DescribeLockTag(&buf, &locallock->tag.lock);
1175 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1176 lockmode);
1177
1178 /* Gather a list of all lock holders and waiters */
1179 LWLockAcquire(partitionLock, LW_SHARED);
1180 GetLockHoldersAndWaiters(locallock, &lock_holders_sbuf,
1181 &lock_waiters_sbuf, &lockHoldersNum);
1182 LWLockRelease(partitionLock);
1183
1184 ereport(LOG,
1185 (errmsg("process %d could not obtain %s on %s",
1186 MyProcPid, modename, buf.data),
1188 "Process holding the lock: %s, Wait queue: %s.",
1189 "Processes holding the lock: %s, Wait queue: %s.",
1190 lockHoldersNum,
1191 lock_holders_sbuf.data,
1192 lock_waiters_sbuf.data)));
1193
1194 pfree(buf.data);
1195 pfree(lock_holders_sbuf.data);
1196 pfree(lock_waiters_sbuf.data);
1197 }
1198 if (locallockp)
1199 *locallockp = NULL;
1200 return LOCKACQUIRE_NOT_AVAIL;
1201 }
1202 else
1203 {
1205 /* DeadLockReport() will not return */
1206 }
1207 }
1208
1209 /*
1210 * We are now in the lock queue, or the lock was already granted. If
1211 * queued, go to sleep.
1212 */
1213 if (waitResult == PROC_WAIT_STATUS_WAITING)
1214 {
1215 Assert(!dontWait);
1216 PROCLOCK_PRINT("LockAcquire: sleeping on lock", proclock);
1217 LOCK_PRINT("LockAcquire: sleeping on lock", lock, lockmode);
1218 LWLockRelease(partitionLock);
1219
1220 waitResult = WaitOnLock(locallock, owner);
1221
1222 /*
1223 * NOTE: do not do any material change of state between here and
1224 * return. All required changes in locktable state must have been
1225 * done when the lock was granted to us --- see notes in WaitOnLock.
1226 */
1227
1228 if (waitResult == PROC_WAIT_STATUS_ERROR)
1229 {
1230 /*
1231 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
1232 * now.
1233 */
1234 Assert(!dontWait);
1236 /* DeadLockReport() will not return */
1237 }
1238 }
1239 else
1240 LWLockRelease(partitionLock);
1241 Assert(waitResult == PROC_WAIT_STATUS_OK);
1242
1243 /* The lock was granted to us. Update the local lock entry accordingly */
1244 Assert((proclock->holdMask & LOCKBIT_ON(lockmode)) != 0);
1245 GrantLockLocal(locallock, owner);
1246
1247 /*
1248 * Lock state is fully up-to-date now; if we error out after this, no
1249 * special error cleanup is required.
1250 */
1252
1253 /*
1254 * Emit a WAL record if acquisition of this lock needs to be replayed in a
1255 * standby server.
1256 */
1257 if (log_lock)
1258 {
1259 /*
1260 * Decode the locktag back to the original values, to avoid sending
1261 * lots of empty bytes with every message. See lock.h to check how a
1262 * locktag is defined for LOCKTAG_RELATION
1263 */
1265 locktag->locktag_field2);
1266 }
1267
1268 return LOCKACQUIRE_OK;
1269}
void DeadLockReport(void)
Definition: deadlock.c:1075
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:956
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1273
#define LOG
Definition: elog.h:31
int MyProcPid
Definition: globals.c:48
@ HASH_ENTER
Definition: hsearch.h:114
static void dlist_delete(dlist_node *node)
Definition: ilist.h:405
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1475
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1282
static bool FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag, uint32 hashcode)
Definition: lock.c:2829
void AbortStrongLockAcquire(void)
Definition: lock.c:1859
static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2750
static int FastPathLocalUseCounts[FP_LOCK_GROUPS_PER_BACKEND_MAX]
Definition: lock.c:176
static ProcWaitStatus WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1931
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:267
static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode)
Definition: lock.c:1823
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition: lock.c:1528
static void FinishStrongLockAcquire(void)
Definition: lock.c:1849
#define RowExclusiveLock
Definition: lockdefs.h:38
void pfree(void *pointer)
Definition: mcxt.c:2152
static char * buf
Definition: pg_test_fsync.c:72
ProcWaitStatus
Definition: proc.h:132
@ PROC_WAIT_STATUS_OK
Definition: proc.h:133
@ PROC_WAIT_STATUS_WAITING
Definition: proc.h:134
@ PROC_WAIT_STATUS_ERROR
Definition: proc.h:135
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
ProcWaitStatus JoinWaitQueue(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait)
Definition: proc.c:1141
void GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
Definition: proc.c:1901
void LogAccessExclusiveLockPrepare(void)
Definition: standby.c:1448
void LogAccessExclusiveLock(Oid dbOid, Oid relOid)
Definition: standby.c:1431
int maxLockOwners
Definition: lock.h:438
bool lockCleared
Definition: lock.h:441
bool RecoveryInProgress(void)
Definition: xlog.c:6522
#define XLogStandbyInfoActive()
Definition: xlog.h:123
bool InRecovery
Definition: xlogutils.c:50

References AbortStrongLockAcquire(), AccessExclusiveLock, Assert(), BeginStrongLockAcquire(), buf, ConflictsWithRelationFastPath, LockMethodData::conflictTab, FastPathStrongRelationLockData::count, CurrentResourceOwner, StringInfoData::data, DeadLockReport(), DescribeLockTag(), dlist_delete(), EligibleForRelationFastPath, elog, ereport, errcode(), errdetail_log_plural(), errhint(), errmsg(), ERROR, FAST_PATH_REL_GROUP, FastPathGrantRelationLock(), FastPathLocalUseCounts, FastPathStrongLockHashPartition, FastPathStrongRelationLocks, FastPathTransferRelationLocks(), FinishStrongLockAcquire(), FP_LOCK_SLOTS_PER_GROUP, PGPROC::fpInfoLock, GetLockHoldersAndWaiters(), GetLockmodeName(), GrantLock(), GrantLockLocal(), HASH_ENTER, HASH_REMOVE, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PROCLOCK::holdMask, LOCALLOCK::holdsStrongLockCount, initStringInfo(), InRecovery, JoinWaitQueue(), lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKACQUIRE_ALREADY_CLEAR, LOCKACQUIRE_ALREADY_HELD, LOCKACQUIRE_NOT_AVAIL, LOCKACQUIRE_OK, LOCKBIT_ON, LockCheckConflicts(), LOCALLOCK::lockCleared, LockHashPartitionLock, PROCLOCK::lockLink, LockMethodLocalHash, LockMethodProcLockHash, LockMethods, LockMethodData::lockModeNames, LOCALLOCK::lockOwners, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOCKTAG_OBJECT, LOCKTAG_RELATION, LOCKTAG::locktag_type, LockTagHashCode(), LOG, LogAccessExclusiveLock(), LogAccessExclusiveLockPrepare(), LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), LOCALLOCK::maxLockOwners, MemoryContextAlloc(), MemSet, LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, MyProcPid, LOCK::nGranted, LOCALLOCK::nLocks, LOCK::nRequested, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, PANIC, pfree(), PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_OK, PROC_WAIT_STATUS_WAITING, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, ProcLockHashCode(), RecoveryInProgress(), RemoveLocalLock(), repalloc(), LOCK::requested, RowExclusiveLock, SetupLockInTable(), PROCLOCK::tag, LOCALLOCK::tag, TopMemoryContext, LOCK::waitMask, WaitOnLock(), and XLogStandbyInfoActive.

Referenced by ConditionalLockDatabaseObject(), ConditionalLockRelation(), ConditionalLockRelationOid(), ConditionalLockSharedObject(), ConditionalLockTuple(), ConditionalXactLockTableWait(), LockAcquire(), LockRelation(), LockRelationId(), and LockRelationOid().

◆ LockCheckConflicts()

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

Definition at line 1528 of file lock.c.

1532{
1533 int numLockModes = lockMethodTable->numLockModes;
1534 LOCKMASK myLocks;
1535 int conflictMask = lockMethodTable->conflictTab[lockmode];
1536 int conflictsRemaining[MAX_LOCKMODES];
1537 int totalConflictsRemaining = 0;
1538 dlist_iter proclock_iter;
1539 int i;
1540
1541 /*
1542 * first check for global conflicts: If no locks conflict with my request,
1543 * then I get the lock.
1544 *
1545 * Checking for conflict: lock->grantMask represents the types of
1546 * currently held locks. conflictTable[lockmode] has a bit set for each
1547 * type of lock that conflicts with request. Bitwise compare tells if
1548 * there is a conflict.
1549 */
1550 if (!(conflictMask & lock->grantMask))
1551 {
1552 PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1553 return false;
1554 }
1555
1556 /*
1557 * Rats. Something conflicts. But it could still be my own lock, or a
1558 * lock held by another member of my locking group. First, figure out how
1559 * many conflicts remain after subtracting out any locks I hold myself.
1560 */
1561 myLocks = proclock->holdMask;
1562 for (i = 1; i <= numLockModes; i++)
1563 {
1564 if ((conflictMask & LOCKBIT_ON(i)) == 0)
1565 {
1566 conflictsRemaining[i] = 0;
1567 continue;
1568 }
1569 conflictsRemaining[i] = lock->granted[i];
1570 if (myLocks & LOCKBIT_ON(i))
1571 --conflictsRemaining[i];
1572 totalConflictsRemaining += conflictsRemaining[i];
1573 }
1574
1575 /* If no conflicts remain, we get the lock. */
1576 if (totalConflictsRemaining == 0)
1577 {
1578 PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1579 return false;
1580 }
1581
1582 /* If no group locking, it's definitely a conflict. */
1583 if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL)
1584 {
1585 Assert(proclock->tag.myProc == MyProc);
1586 PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1587 proclock);
1588 return true;
1589 }
1590
1591 /*
1592 * The relation extension lock conflict even between the group members.
1593 */
1595 {
1596 PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)",
1597 proclock);
1598 return true;
1599 }
1600
1601 /*
1602 * Locks held in conflicting modes by members of our own lock group are
1603 * not real conflicts; we can subtract those out and see if we still have
1604 * a conflict. This is O(N) in the number of processes holding or
1605 * awaiting locks on this object. We could improve that by making the
1606 * shared memory state more complex (and larger) but it doesn't seem worth
1607 * it.
1608 */
1609 dlist_foreach(proclock_iter, &lock->procLocks)
1610 {
1611 PROCLOCK *otherproclock =
1612 dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
1613
1614 if (proclock != otherproclock &&
1615 proclock->groupLeader == otherproclock->groupLeader &&
1616 (otherproclock->holdMask & conflictMask) != 0)
1617 {
1618 int intersectMask = otherproclock->holdMask & conflictMask;
1619
1620 for (i = 1; i <= numLockModes; i++)
1621 {
1622 if ((intersectMask & LOCKBIT_ON(i)) != 0)
1623 {
1624 if (conflictsRemaining[i] <= 0)
1625 elog(PANIC, "proclocks held do not match lock");
1626 conflictsRemaining[i]--;
1627 totalConflictsRemaining--;
1628 }
1629 }
1630
1631 if (totalConflictsRemaining == 0)
1632 {
1633 PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1634 proclock);
1635 return false;
1636 }
1637 }
1638 }
1639
1640 /* Nope, it's a real conflict. */
1641 PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1642 return true;
1643}
#define LOCK_LOCKTAG(lock)
Definition: lock.h:326

References Assert(), LockMethodData::conflictTab, dlist_iter::cur, dlist_container, dlist_foreach, elog, LOCK::granted, LOCK::grantMask, PROCLOCK::groupLeader, PROCLOCK::holdMask, i, LOCK_LOCKTAG, LOCKBIT_ON, PGPROC::lockGroupLeader, LOCKTAG_RELATION_EXTEND, MAX_LOCKMODES, MyProc, PROCLOCKTAG::myProc, LockMethodData::numLockModes, PANIC, PROCLOCK_PRINT, LOCK::procLocks, and PROCLOCK::tag.

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

◆ LockHasWaiters()

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

Definition at line 695 of file lock.c.

696{
697 LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
698 LockMethod lockMethodTable;
699 LOCALLOCKTAG localtag;
700 LOCALLOCK *locallock;
701 LOCK *lock;
702 PROCLOCK *proclock;
703 LWLock *partitionLock;
704 bool hasWaiters = false;
705
706 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
707 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
708 lockMethodTable = LockMethods[lockmethodid];
709 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
710 elog(ERROR, "unrecognized lock mode: %d", lockmode);
711
712#ifdef LOCK_DEBUG
713 if (LOCK_DEBUG_ENABLED(locktag))
714 elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
715 locktag->locktag_field1, locktag->locktag_field2,
716 lockMethodTable->lockModeNames[lockmode]);
717#endif
718
719 /*
720 * Find the LOCALLOCK entry for this lock and lockmode
721 */
722 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
723 localtag.lock = *locktag;
724 localtag.mode = lockmode;
725
727 &localtag,
728 HASH_FIND, NULL);
729
730 /*
731 * let the caller print its own error message, too. Do not ereport(ERROR).
732 */
733 if (!locallock || locallock->nLocks <= 0)
734 {
735 elog(WARNING, "you don't own a lock of type %s",
736 lockMethodTable->lockModeNames[lockmode]);
737 return false;
738 }
739
740 /*
741 * Check the shared lock table.
742 */
743 partitionLock = LockHashPartitionLock(locallock->hashcode);
744
745 LWLockAcquire(partitionLock, LW_SHARED);
746
747 /*
748 * We don't need to re-find the lock or proclock, since we kept their
749 * addresses in the locallock table, and they couldn't have been removed
750 * while we were holding a lock on them.
751 */
752 lock = locallock->lock;
753 LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
754 proclock = locallock->proclock;
755 PROCLOCK_PRINT("LockHasWaiters: found", proclock);
756
757 /*
758 * Double-check that we are actually holding a lock of the type we want to
759 * release.
760 */
761 if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
762 {
763 PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
764 LWLockRelease(partitionLock);
765 elog(WARNING, "you don't own a lock of type %s",
766 lockMethodTable->lockModeNames[lockmode]);
767 RemoveLocalLock(locallock);
768 return false;
769 }
770
771 /*
772 * Do the checking.
773 */
774 if ((lockMethodTable->conflictTab[lockmode] & lock->waitMask) != 0)
775 hasWaiters = true;
776
777 LWLockRelease(partitionLock);
778
779 return hasWaiters;
780}
#define WARNING
Definition: elog.h:36

References LockMethodData::conflictTab, elog, ERROR, HASH_FIND, hash_search(), LOCALLOCK::hashcode, PROCLOCK::holdMask, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLock, LockMethodLocalHash, LockMethods, LockMethodData::lockModeNames, 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().

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode,
bool  orstronger 
)

Definition at line 642 of file lock.c.

644{
645 LOCALLOCKTAG localtag;
646 LOCALLOCK *locallock;
647
648 /*
649 * See if there is a LOCALLOCK entry for this lock and lockmode
650 */
651 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
652 localtag.lock = *locktag;
653 localtag.mode = lockmode;
654
656 &localtag,
657 HASH_FIND, NULL);
658
659 if (locallock && locallock->nLocks > 0)
660 return true;
661
662 if (orstronger)
663 {
664 LOCKMODE slockmode;
665
666 for (slockmode = lockmode + 1;
667 slockmode <= MaxLockMode;
668 slockmode++)
669 {
670 if (LockHeldByMe(locktag, slockmode, false))
671 return true;
672 }
673 }
674
675 return false;
676}
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition: lock.c:642
#define MaxLockMode
Definition: lockdefs.h:45

References HASH_FIND, hash_search(), LOCALLOCKTAG::lock, LockHeldByMe(), LockMethodLocalHash, MaxLockMode, MemSet, LOCALLOCKTAG::mode, and LOCALLOCK::nLocks.

Referenced by CheckRelationLockedByMe(), CheckRelationOidLockedByMe(), and LockHeldByMe().

◆ LockManagerShmemInit()

void LockManagerShmemInit ( void  )

Definition at line 443 of file lock.c.

444{
445 HASHCTL info;
446 long init_table_size,
447 max_table_size;
448 bool found;
449
450 /*
451 * Compute init/max size to request for lock hashtables. Note these
452 * calculations must agree with LockManagerShmemSize!
453 */
454 max_table_size = NLOCKENTS();
455 init_table_size = max_table_size / 2;
456
457 /*
458 * Allocate hash table for LOCK structs. This stores per-locked-object
459 * information.
460 */
461 info.keysize = sizeof(LOCKTAG);
462 info.entrysize = sizeof(LOCK);
464
465 LockMethodLockHash = ShmemInitHash("LOCK hash",
466 init_table_size,
467 max_table_size,
468 &info,
470
471 /* Assume an average of 2 holders per lock */
472 max_table_size *= 2;
473 init_table_size *= 2;
474
475 /*
476 * Allocate hash table for PROCLOCK structs. This stores
477 * per-lock-per-holder information.
478 */
479 info.keysize = sizeof(PROCLOCKTAG);
480 info.entrysize = sizeof(PROCLOCK);
481 info.hash = proclock_hash;
483
484 LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
485 init_table_size,
486 max_table_size,
487 &info,
489
490 /*
491 * Allocate fast-path structures.
492 */
494 ShmemInitStruct("Fast Path Strong Relation Lock Data",
495 sizeof(FastPathStrongRelationLockData), &found);
496 if (!found)
498}
#define HASH_FUNCTION
Definition: hsearch.h:98
#define HASH_PARTITION
Definition: hsearch.h:92
#define NLOCKENTS()
Definition: lock.c:56
static uint32 proclock_hash(const void *key, Size keysize)
Definition: lock.c:573
struct LOCK LOCK
struct PROCLOCK PROCLOCK
struct LOCKTAG LOCKTAG
struct PROCLOCKTAG PROCLOCKTAG
HTAB * ShmemInitHash(const char *name, long init_size, long max_size, HASHCTL *infoP, int hash_flags)
Definition: shmem.c:332
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
#define SpinLockInit(lock)
Definition: spin.h:57
HashValueFunc hash
Definition: hsearch.h:78
long num_partitions
Definition: hsearch.h:68

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

Referenced by CreateOrAttachShmemStructs().

◆ LockManagerShmemSize()

Size LockManagerShmemSize ( void  )

Definition at line 3726 of file lock.c.

3727{
3728 Size size = 0;
3729 long max_table_size;
3730
3731 /* lock hash table */
3732 max_table_size = NLOCKENTS();
3733 size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3734
3735 /* proclock hash table */
3736 max_table_size *= 2;
3737 size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3738
3739 /*
3740 * Since NLOCKENTS is only an estimate, add 10% safety margin.
3741 */
3742 size = add_size(size, size / 10);
3743
3744 return size;
3745}
size_t Size
Definition: c.h:576
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:784
Size add_size(Size s1, Size s2)
Definition: shmem.c:493

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

Referenced by CalculateShmemSize().

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2674 of file lock.c.

2675{
2677
2678 Assert(parent != NULL);
2679
2680 if (locallocks == NULL)
2681 {
2682 HASH_SEQ_STATUS status;
2683 LOCALLOCK *locallock;
2684
2686
2687 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2688 LockReassignOwner(locallock, parent);
2689 }
2690 else
2691 {
2692 int i;
2693
2694 for (i = nlocks - 1; i >= 0; i--)
2695 LockReassignOwner(locallocks[i], parent);
2696 }
2697}
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2704
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition: resowner.c:905

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

Referenced by ResourceOwnerReleaseInternal().

◆ LockRelease()

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

Definition at line 2070 of file lock.c.

2071{
2072 LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
2073 LockMethod lockMethodTable;
2074 LOCALLOCKTAG localtag;
2075 LOCALLOCK *locallock;
2076 LOCK *lock;
2077 PROCLOCK *proclock;
2078 LWLock *partitionLock;
2079 bool wakeupNeeded;
2080
2081 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2082 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2083 lockMethodTable = LockMethods[lockmethodid];
2084 if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2085 elog(ERROR, "unrecognized lock mode: %d", lockmode);
2086
2087#ifdef LOCK_DEBUG
2088 if (LOCK_DEBUG_ENABLED(locktag))
2089 elog(LOG, "LockRelease: lock [%u,%u] %s",
2090 locktag->locktag_field1, locktag->locktag_field2,
2091 lockMethodTable->lockModeNames[lockmode]);
2092#endif
2093
2094 /*
2095 * Find the LOCALLOCK entry for this lock and lockmode
2096 */
2097 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
2098 localtag.lock = *locktag;
2099 localtag.mode = lockmode;
2100
2102 &localtag,
2103 HASH_FIND, NULL);
2104
2105 /*
2106 * let the caller print its own error message, too. Do not ereport(ERROR).
2107 */
2108 if (!locallock || locallock->nLocks <= 0)
2109 {
2110 elog(WARNING, "you don't own a lock of type %s",
2111 lockMethodTable->lockModeNames[lockmode]);
2112 return false;
2113 }
2114
2115 /*
2116 * Decrease the count for the resource owner.
2117 */
2118 {
2119 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2120 ResourceOwner owner;
2121 int i;
2122
2123 /* Identify owner for lock */
2124 if (sessionLock)
2125 owner = NULL;
2126 else
2127 owner = CurrentResourceOwner;
2128
2129 for (i = locallock->numLockOwners - 1; i >= 0; i--)
2130 {
2131 if (lockOwners[i].owner == owner)
2132 {
2133 Assert(lockOwners[i].nLocks > 0);
2134 if (--lockOwners[i].nLocks == 0)
2135 {
2136 if (owner != NULL)
2137 ResourceOwnerForgetLock(owner, locallock);
2138 /* compact out unused slot */
2139 locallock->numLockOwners--;
2140 if (i < locallock->numLockOwners)
2141 lockOwners[i] = lockOwners[locallock->numLockOwners];
2142 }
2143 break;
2144 }
2145 }
2146 if (i < 0)
2147 {
2148 /* don't release a lock belonging to another owner */
2149 elog(WARNING, "you don't own a lock of type %s",
2150 lockMethodTable->lockModeNames[lockmode]);
2151 return false;
2152 }
2153 }
2154
2155 /*
2156 * Decrease the total local count. If we're still holding the lock, we're
2157 * done.
2158 */
2159 locallock->nLocks--;
2160
2161 if (locallock->nLocks > 0)
2162 return true;
2163
2164 /*
2165 * At this point we can no longer suppose we are clear of invalidation
2166 * messages related to this lock. Although we'll delete the LOCALLOCK
2167 * object before any intentional return from this routine, it seems worth
2168 * the trouble to explicitly reset lockCleared right now, just in case
2169 * some error prevents us from deleting the LOCALLOCK.
2170 */
2171 locallock->lockCleared = false;
2172
2173 /* Attempt fast release of any lock eligible for the fast path. */
2174 if (EligibleForRelationFastPath(locktag, lockmode) &&
2176 {
2177 bool released;
2178
2179 /*
2180 * We might not find the lock here, even if we originally entered it
2181 * here. Another backend may have moved it to the main table.
2182 */
2184 released = FastPathUnGrantRelationLock(locktag->locktag_field2,
2185 lockmode);
2187 if (released)
2188 {
2189 RemoveLocalLock(locallock);
2190 return true;
2191 }
2192 }
2193
2194 /*
2195 * Otherwise we've got to mess with the shared lock table.
2196 */
2197 partitionLock = LockHashPartitionLock(locallock->hashcode);
2198
2199 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2200
2201 /*
2202 * Normally, we don't need to re-find the lock or proclock, since we kept
2203 * their addresses in the locallock table, and they couldn't have been
2204 * removed while we were holding a lock on them. But it's possible that
2205 * the lock was taken fast-path and has since been moved to the main hash
2206 * table by another backend, in which case we will need to look up the
2207 * objects here. We assume the lock field is NULL if so.
2208 */
2209 lock = locallock->lock;
2210 if (!lock)
2211 {
2212 PROCLOCKTAG proclocktag;
2213
2214 Assert(EligibleForRelationFastPath(locktag, lockmode));
2216 locktag,
2217 locallock->hashcode,
2218 HASH_FIND,
2219 NULL);
2220 if (!lock)
2221 elog(ERROR, "failed to re-find shared lock object");
2222 locallock->lock = lock;
2223
2224 proclocktag.myLock = lock;
2225 proclocktag.myProc = MyProc;
2227 &proclocktag,
2228 HASH_FIND,
2229 NULL);
2230 if (!locallock->proclock)
2231 elog(ERROR, "failed to re-find shared proclock object");
2232 }
2233 LOCK_PRINT("LockRelease: found", lock, lockmode);
2234 proclock = locallock->proclock;
2235 PROCLOCK_PRINT("LockRelease: found", proclock);
2236
2237 /*
2238 * Double-check that we are actually holding a lock of the type we want to
2239 * release.
2240 */
2241 if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2242 {
2243 PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
2244 LWLockRelease(partitionLock);
2245 elog(WARNING, "you don't own a lock of type %s",
2246 lockMethodTable->lockModeNames[lockmode]);
2247 RemoveLocalLock(locallock);
2248 return false;
2249 }
2250
2251 /*
2252 * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2253 */
2254 wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2255
2256 CleanUpLock(lock, proclock,
2257 lockMethodTable, locallock->hashcode,
2258 wakeupNeeded);
2259
2260 LWLockRelease(partitionLock);
2261
2262 RemoveLocalLock(locallock);
2263 return true;
2264}
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1680
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1737
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2793
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:1082

References Assert(), CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FAST_PATH_REL_GROUP, FastPathLocalUseCounts, FastPathUnGrantRelationLock(), PGPROC::fpInfoLock, HASH_FIND, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PROCLOCK::holdMask, i, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, LOCALLOCK::lockCleared, LockHashPartitionLock, LockMethodLocalHash, LockMethodLockHash, LockMethodProcLockHash, LockMethods, LockMethodData::lockModeNames, LOCALLOCK::lockOwners, 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(), SearchSysCacheLocked1(), SpeculativeInsertionLockRelease(), SpeculativeInsertionWait(), StandbyReleaseXidEntryLocks(), UnlockApplyTransactionForSession(), UnlockDatabaseObject(), UnlockPage(), UnlockRelation(), UnlockRelationForExtension(), UnlockRelationId(), UnlockRelationIdForSession(), UnlockRelationOid(), UnlockSharedObject(), UnlockSharedObjectForSession(), UnlockTuple(), VirtualXactLock(), XactLockForVirtualXact(), XactLockTableDelete(), and XactLockTableWait().

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2275 of file lock.c.

2276{
2277 HASH_SEQ_STATUS status;
2278 LockMethod lockMethodTable;
2279 int i,
2280 numLockModes;
2281 LOCALLOCK *locallock;
2282 LOCK *lock;
2283 int partition;
2284 bool have_fast_path_lwlock = false;
2285
2286 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2287 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2288 lockMethodTable = LockMethods[lockmethodid];
2289
2290#ifdef LOCK_DEBUG
2291 if (*(lockMethodTable->trace_flag))
2292 elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2293#endif
2294
2295 /*
2296 * Get rid of our fast-path VXID lock, if appropriate. Note that this is
2297 * the only way that the lock we hold on our own VXID can ever get
2298 * released: it is always and only released when a toplevel transaction
2299 * ends.
2300 */
2301 if (lockmethodid == DEFAULT_LOCKMETHOD)
2303
2304 numLockModes = lockMethodTable->numLockModes;
2305
2306 /*
2307 * First we run through the locallock table and get rid of unwanted
2308 * entries, then we scan the process's proclocks and get rid of those. We
2309 * do this separately because we may have multiple locallock entries
2310 * pointing to the same proclock, and we daren't end up with any dangling
2311 * pointers. Fast-path locks are cleaned up during the locallock table
2312 * scan, though.
2313 */
2315
2316 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2317 {
2318 /*
2319 * If the LOCALLOCK entry is unused, something must've gone wrong
2320 * while trying to acquire this lock. Just forget the local entry.
2321 */
2322 if (locallock->nLocks == 0)
2323 {
2324 RemoveLocalLock(locallock);
2325 continue;
2326 }
2327
2328 /* Ignore items that are not of the lockmethod to be removed */
2329 if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2330 continue;
2331
2332 /*
2333 * If we are asked to release all locks, we can just zap the entry.
2334 * Otherwise, must scan to see if there are session locks. We assume
2335 * there is at most one lockOwners entry for session locks.
2336 */
2337 if (!allLocks)
2338 {
2339 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2340
2341 /* If session lock is above array position 0, move it down to 0 */
2342 for (i = 0; i < locallock->numLockOwners; i++)
2343 {
2344 if (lockOwners[i].owner == NULL)
2345 lockOwners[0] = lockOwners[i];
2346 else
2347 ResourceOwnerForgetLock(lockOwners[i].owner, locallock);
2348 }
2349
2350 if (locallock->numLockOwners > 0 &&
2351 lockOwners[0].owner == NULL &&
2352 lockOwners[0].nLocks > 0)
2353 {
2354 /* Fix the locallock to show just the session locks */
2355 locallock->nLocks = lockOwners[0].nLocks;
2356 locallock->numLockOwners = 1;
2357 /* We aren't deleting this locallock, so done */
2358 continue;
2359 }
2360 else
2361 locallock->numLockOwners = 0;
2362 }
2363
2364#ifdef USE_ASSERT_CHECKING
2365
2366 /*
2367 * Tuple locks are currently held only for short durations within a
2368 * transaction. Check that we didn't forget to release one.
2369 */
2370 if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_TUPLE && !allLocks)
2371 elog(WARNING, "tuple lock held at commit");
2372#endif
2373
2374 /*
2375 * If the lock or proclock pointers are NULL, this lock was taken via
2376 * the relation fast-path (and is not known to have been transferred).
2377 */
2378 if (locallock->proclock == NULL || locallock->lock == NULL)
2379 {
2380 LOCKMODE lockmode = locallock->tag.mode;
2381 Oid relid;
2382
2383 /* Verify that a fast-path lock is what we've got. */
2384 if (!EligibleForRelationFastPath(&locallock->tag.lock, lockmode))
2385 elog(PANIC, "locallock table corrupted");
2386
2387 /*
2388 * If we don't currently hold the LWLock that protects our
2389 * fast-path data structures, we must acquire it before attempting
2390 * to release the lock via the fast-path. We will continue to
2391 * hold the LWLock until we're done scanning the locallock table,
2392 * unless we hit a transferred fast-path lock. (XXX is this
2393 * really such a good idea? There could be a lot of entries ...)
2394 */
2395 if (!have_fast_path_lwlock)
2396 {
2398 have_fast_path_lwlock = true;
2399 }
2400
2401 /* Attempt fast-path release. */
2402 relid = locallock->tag.lock.locktag_field2;
2403 if (FastPathUnGrantRelationLock(relid, lockmode))
2404 {
2405 RemoveLocalLock(locallock);
2406 continue;
2407 }
2408
2409 /*
2410 * Our lock, originally taken via the fast path, has been
2411 * transferred to the main lock table. That's going to require
2412 * some extra work, so release our fast-path lock before starting.
2413 */
2415 have_fast_path_lwlock = false;
2416
2417 /*
2418 * Now dump the lock. We haven't got a pointer to the LOCK or
2419 * PROCLOCK in this case, so we have to handle this a bit
2420 * differently than a normal lock release. Unfortunately, this
2421 * requires an extra LWLock acquire-and-release cycle on the
2422 * partitionLock, but hopefully it shouldn't happen often.
2423 */
2424 LockRefindAndRelease(lockMethodTable, MyProc,
2425 &locallock->tag.lock, lockmode, false);
2426 RemoveLocalLock(locallock);
2427 continue;
2428 }
2429
2430 /* Mark the proclock to show we need to release this lockmode */
2431 if (locallock->nLocks > 0)
2432 locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
2433
2434 /* And remove the locallock hashtable entry */
2435 RemoveLocalLock(locallock);
2436 }
2437
2438 /* Done with the fast-path data structures */
2439 if (have_fast_path_lwlock)
2441
2442 /*
2443 * Now, scan each lock partition separately.
2444 */
2445 for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
2446 {
2447 LWLock *partitionLock;
2448 dlist_head *procLocks = &MyProc->myProcLocks[partition];
2449 dlist_mutable_iter proclock_iter;
2450
2451 partitionLock = LockHashPartitionLockByIndex(partition);
2452
2453 /*
2454 * If the proclock list for this partition is empty, we can skip
2455 * acquiring the partition lock. This optimization is trickier than
2456 * it looks, because another backend could be in process of adding
2457 * something to our proclock list due to promoting one of our
2458 * fast-path locks. However, any such lock must be one that we
2459 * decided not to delete above, so it's okay to skip it again now;
2460 * we'd just decide not to delete it again. We must, however, be
2461 * careful to re-fetch the list header once we've acquired the
2462 * partition lock, to be sure we have a valid, up-to-date pointer.
2463 * (There is probably no significant risk if pointer fetch/store is
2464 * atomic, but we don't wish to assume that.)
2465 *
2466 * XXX This argument assumes that the locallock table correctly
2467 * represents all of our fast-path locks. While allLocks mode
2468 * guarantees to clean up all of our normal locks regardless of the
2469 * locallock situation, we lose that guarantee for fast-path locks.
2470 * This is not ideal.
2471 */
2472 if (dlist_is_empty(procLocks))
2473 continue; /* needn't examine this partition */
2474
2475 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2476
2477 dlist_foreach_modify(proclock_iter, procLocks)
2478 {
2479 PROCLOCK *proclock = dlist_container(PROCLOCK, procLink, proclock_iter.cur);
2480 bool wakeupNeeded = false;
2481
2482 Assert(proclock->tag.myProc == MyProc);
2483
2484 lock = proclock->tag.myLock;
2485
2486 /* Ignore items that are not of the lockmethod to be removed */
2487 if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
2488 continue;
2489
2490 /*
2491 * In allLocks mode, force release of all locks even if locallock
2492 * table had problems
2493 */
2494 if (allLocks)
2495 proclock->releaseMask = proclock->holdMask;
2496 else
2497 Assert((proclock->releaseMask & ~proclock->holdMask) == 0);
2498
2499 /*
2500 * Ignore items that have nothing to be released, unless they have
2501 * holdMask == 0 and are therefore recyclable
2502 */
2503 if (proclock->releaseMask == 0 && proclock->holdMask != 0)
2504 continue;
2505
2506 PROCLOCK_PRINT("LockReleaseAll", proclock);
2507 LOCK_PRINT("LockReleaseAll", lock, 0);
2508 Assert(lock->nRequested >= 0);
2509 Assert(lock->nGranted >= 0);
2510 Assert(lock->nGranted <= lock->nRequested);
2511 Assert((proclock->holdMask & ~lock->grantMask) == 0);
2512
2513 /*
2514 * Release the previously-marked lock modes
2515 */
2516 for (i = 1; i <= numLockModes; i++)
2517 {
2518 if (proclock->releaseMask & LOCKBIT_ON(i))
2519 wakeupNeeded |= UnGrantLock(lock, i, proclock,
2520 lockMethodTable);
2521 }
2522 Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
2523 Assert(lock->nGranted <= lock->nRequested);
2524 LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2525
2526 proclock->releaseMask = 0;
2527
2528 /* CleanUpLock will wake up waiters if needed. */
2529 CleanUpLock(lock, proclock,
2530 lockMethodTable,
2531 LockTagHashCode(&lock->tag),
2532 wakeupNeeded);
2533 } /* loop over PROCLOCKs within this partition */
2534
2535 LWLockRelease(partitionLock);
2536 } /* loop over partitions */
2537
2538#ifdef LOCK_DEBUG
2539 if (*(lockMethodTable->trace_flag))
2540 elog(LOG, "LockReleaseAll done");
2541#endif
2542}
#define dlist_foreach_modify(iter, lhead)
Definition: ilist.h:640
void VirtualXactLockTableCleanup(void)
Definition: lock.c:4613
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:444
#define LOCALLOCK_LOCKTAG(llock)
Definition: lock.h:445
int64 nLocks
Definition: lock.h:424
const bool * trace_flag
Definition: lock.h:114
dlist_node * cur
Definition: ilist.h:200

References Assert(), CleanUpLock(), dlist_mutable_iter::cur, DEFAULT_LOCKMETHOD, dlist_container, dlist_foreach_modify, dlist_is_empty(), EligibleForRelationFastPath, elog, ERROR, FastPathUnGrantRelationLock(), PGPROC::fpInfoLock, LOCK::grantMask, hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, i, lengthof, LOCALLOCK_LOCKMETHOD, LOCALLOCK_LOCKTAG, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_LOCKMETHOD, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLockByIndex, LockMethodLocalHash, LockMethods, LOCALLOCK::lockOwners, LockRefindAndRelease(), LOCKTAG::locktag_field2, LOCKTAG_TUPLE, 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, LOCALLOCKOWNER::owner, PANIC, LOCALLOCK::proclock, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), ResourceOwnerForgetLock(), LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, LockMethodData::trace_flag, UnGrantLock(), VirtualXactLockTableCleanup(), and WARNING.

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

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2579 of file lock.c.

2580{
2581 if (locallocks == NULL)
2582 {
2583 HASH_SEQ_STATUS status;
2584 LOCALLOCK *locallock;
2585
2587
2588 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2589 ReleaseLockIfHeld(locallock, false);
2590 }
2591 else
2592 {
2593 int i;
2594
2595 for (i = nlocks - 1; i >= 0; i--)
2596 ReleaseLockIfHeld(locallocks[i], false);
2597 }
2598}
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2614

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

Referenced by ResourceOwnerReleaseInternal().

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

Definition at line 2549 of file lock.c.

2550{
2551 HASH_SEQ_STATUS status;
2552 LOCALLOCK *locallock;
2553
2554 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2555 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2556
2558
2559 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2560 {
2561 /* Ignore items that are not of the specified lock method */
2562 if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2563 continue;
2564
2565 ReleaseLockIfHeld(locallock, true);
2566 }
2567}

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

Referenced by pg_advisory_unlock_all().

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 556 of file lock.c.

557{
558 return get_hash_value(LockMethodLockHash, locktag);
559}
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition: dynahash.c:912

References get_hash_value(), and LockMethodLockHash.

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

Definition at line 4824 of file lock.c.

4825{
4826 LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4827 LOCK *lock;
4828 bool found;
4829 uint32 hashcode;
4830 LWLock *partitionLock;
4831 int waiters = 0;
4832
4833 if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4834 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4835
4836 hashcode = LockTagHashCode(locktag);
4837 partitionLock = LockHashPartitionLock(hashcode);
4838 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4839
4841 locktag,
4842 hashcode,
4843 HASH_FIND,
4844 &found);
4845 if (found)
4846 {
4847 Assert(lock != NULL);
4848 waiters = lock->nRequested;
4849 }
4850 LWLockRelease(partitionLock);
4851
4852 return waiters;
4853}

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

Referenced by RelationExtensionLockWaiterCount().

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

Definition at line 3542 of file lock.c.

3543{
3544 PGPROC *newproc = TwoPhaseGetDummyProc(xid, false);
3545 HASH_SEQ_STATUS status;
3546 LOCALLOCK *locallock;
3547 LOCK *lock;
3548 PROCLOCK *proclock;
3549 PROCLOCKTAG proclocktag;
3550 int partition;
3551
3552 /* Can't prepare a lock group follower. */
3553 Assert(MyProc->lockGroupLeader == NULL ||
3555
3556 /* This is a critical section: any error means big trouble */
3558
3559 /*
3560 * First we run through the locallock table and get rid of unwanted
3561 * entries, then we scan the process's proclocks and transfer them to the
3562 * target proc.
3563 *
3564 * We do this separately because we may have multiple locallock entries
3565 * pointing to the same proclock, and we daren't end up with any dangling
3566 * pointers.
3567 */
3569
3570 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3571 {
3572 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3573 bool haveSessionLock;
3574 bool haveXactLock;
3575 int i;
3576
3577 if (locallock->proclock == NULL || locallock->lock == NULL)
3578 {
3579 /*
3580 * We must've run out of shared memory while trying to set up this
3581 * lock. Just forget the local entry.
3582 */
3583 Assert(locallock->nLocks == 0);
3584 RemoveLocalLock(locallock);
3585 continue;
3586 }
3587
3588 /* Ignore VXID locks */
3590 continue;
3591
3592 /* Scan to see whether we hold it at session or transaction level */
3593 haveSessionLock = haveXactLock = false;
3594 for (i = locallock->numLockOwners - 1; i >= 0; i--)
3595 {
3596 if (lockOwners[i].owner == NULL)
3597 haveSessionLock = true;
3598 else
3599 haveXactLock = true;
3600 }
3601
3602 /* Ignore it if we have only session lock */
3603 if (!haveXactLock)
3604 continue;
3605
3606 /* This can't happen, because we already checked it */
3607 if (haveSessionLock)
3608 ereport(PANIC,
3609 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3610 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3611
3612 /* Mark the proclock to show we need to release this lockmode */
3613 if (locallock->nLocks > 0)
3614 locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3615
3616 /* And remove the locallock hashtable entry */
3617 RemoveLocalLock(locallock);
3618 }
3619
3620 /*
3621 * Now, scan each lock partition separately.
3622 */
3623 for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3624 {
3625 LWLock *partitionLock;
3626 dlist_head *procLocks = &(MyProc->myProcLocks[partition]);
3627 dlist_mutable_iter proclock_iter;
3628
3629 partitionLock = LockHashPartitionLockByIndex(partition);
3630
3631 /*
3632 * If the proclock list for this partition is empty, we can skip
3633 * acquiring the partition lock. This optimization is safer than the
3634 * situation in LockReleaseAll, because we got rid of any fast-path
3635 * locks during AtPrepare_Locks, so there cannot be any case where
3636 * another backend is adding something to our lists now. For safety,
3637 * though, we code this the same way as in LockReleaseAll.
3638 */
3639 if (dlist_is_empty(procLocks))
3640 continue; /* needn't examine this partition */
3641
3642 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3643
3644 dlist_foreach_modify(proclock_iter, procLocks)
3645 {
3646 proclock = dlist_container(PROCLOCK, procLink, proclock_iter.cur);
3647
3648 Assert(proclock->tag.myProc == MyProc);
3649
3650 lock = proclock->tag.myLock;
3651
3652 /* Ignore VXID locks */
3654 continue;
3655
3656 PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3657 LOCK_PRINT("PostPrepare_Locks", lock, 0);
3658 Assert(lock->nRequested >= 0);
3659 Assert(lock->nGranted >= 0);
3660 Assert(lock->nGranted <= lock->nRequested);
3661 Assert((proclock->holdMask & ~lock->grantMask) == 0);
3662
3663 /* Ignore it if nothing to release (must be a session lock) */
3664 if (proclock->releaseMask == 0)
3665 continue;
3666
3667 /* Else we should be releasing all locks */
3668 if (proclock->releaseMask != proclock->holdMask)
3669 elog(PANIC, "we seem to have dropped a bit somewhere");
3670
3671 /*
3672 * We cannot simply modify proclock->tag.myProc to reassign
3673 * ownership of the lock, because that's part of the hash key and
3674 * the proclock would then be in the wrong hash chain. Instead
3675 * use hash_update_hash_key. (We used to create a new hash entry,
3676 * but that risks out-of-memory failure if other processes are
3677 * busy making proclocks too.) We must unlink the proclock from
3678 * our procLink chain and put it into the new proc's chain, too.
3679 *
3680 * Note: the updated proclock hash key will still belong to the
3681 * same hash partition, cf proclock_hash(). So the partition lock
3682 * we already hold is sufficient for this.
3683 */
3684 dlist_delete(&proclock->procLink);
3685
3686 /*
3687 * Create the new hash key for the proclock.
3688 */
3689 proclocktag.myLock = lock;
3690 proclocktag.myProc = newproc;
3691
3692 /*
3693 * Update groupLeader pointer to point to the new proc. (We'd
3694 * better not be a member of somebody else's lock group!)
3695 */
3696 Assert(proclock->groupLeader == proclock->tag.myProc);
3697 proclock->groupLeader = newproc;
3698
3699 /*
3700 * Update the proclock. We should not find any existing entry for
3701 * the same hash key, since there can be only one entry for any
3702 * given lock with my own proc.
3703 */
3705 proclock,
3706 &proclocktag))
3707 elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3708
3709 /* Re-link into the new proc's proclock list */
3710 dlist_push_tail(&newproc->myProcLocks[partition], &proclock->procLink);
3711
3712 PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3713 } /* loop over PROCLOCKs within this partition */
3714
3715 LWLockRelease(partitionLock);
3716 } /* loop over partitions */
3717
3719}
bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr)
Definition: dynahash.c:1146
#define START_CRIT_SECTION()
Definition: miscadmin.h:150
#define END_CRIT_SECTION()
Definition: miscadmin.h:152

References Assert(), dlist_mutable_iter::cur, dlist_container, dlist_delete(), dlist_foreach_modify, dlist_is_empty(), dlist_push_tail(), 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, LockMethodLocalHash, LockMethodProcLockHash, 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, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), START_CRIT_SECTION, LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, and TwoPhaseGetDummyProc().

Referenced by PrepareTransaction().

◆ RememberSimpleDeadLock()

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

Definition at line 1147 of file deadlock.c.

1151{
1152 DEADLOCK_INFO *info = &deadlockDetails[0];
1153
1154 info->locktag = lock->tag;
1155 info->lockmode = lockmode;
1156 info->pid = proc1->pid;
1157 info++;
1158 info->locktag = proc2->waitLock->tag;
1159 info->lockmode = proc2->waitLockMode;
1160 info->pid = proc2->pid;
1161 nDeadlockDetails = 2;
1162}

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

Referenced by JoinWaitQueue().

◆ RemoveFromWaitQueue()

void RemoveFromWaitQueue ( PGPROC proc,
uint32  hashcode 
)

Definition at line 2014 of file lock.c.

2015{
2016 LOCK *waitLock = proc->waitLock;
2017 PROCLOCK *proclock = proc->waitProcLock;
2018 LOCKMODE lockmode = proc->waitLockMode;
2019 LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*waitLock);
2020
2021 /* Make sure proc is waiting */
2023 Assert(proc->links.next != NULL);
2024 Assert(waitLock);
2025 Assert(!dclist_is_empty(&waitLock->waitProcs));
2026 Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
2027
2028 /* Remove proc from lock's wait queue */
2029 dclist_delete_from_thoroughly(&waitLock->waitProcs, &proc->links);
2030
2031 /* Undo increments of request counts by waiting process */
2032 Assert(waitLock->nRequested > 0);
2033 Assert(waitLock->nRequested > proc->waitLock->nGranted);
2034 waitLock->nRequested--;
2035 Assert(waitLock->requested[lockmode] > 0);
2036 waitLock->requested[lockmode]--;
2037 /* don't forget to clear waitMask bit if appropriate */
2038 if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
2039 waitLock->waitMask &= LOCKBIT_OFF(lockmode);
2040
2041 /* Clean up the proc's own state, and pass it the ok/fail signal */
2042 proc->waitLock = NULL;
2043 proc->waitProcLock = NULL;
2045
2046 /*
2047 * Delete the proclock immediately if it represents no already-held locks.
2048 * (This must happen now because if the owner of the lock decides to
2049 * release it, and the requested/granted counts then go to zero,
2050 * LockRelease expects there to be no remaining proclocks.) Then see if
2051 * any other waiters for the lock can be woken up now.
2052 */
2053 CleanUpLock(waitLock, proclock,
2054 LockMethods[lockmethodid], hashcode,
2055 true);
2056}
static bool dclist_is_empty(const dclist_head *head)
Definition: ilist.h:682
static void dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node)
Definition: ilist.h:776
PROCLOCK * waitProcLock
Definition: proc.h:242
ProcWaitStatus waitStatus
Definition: proc.h:176
dlist_node links
Definition: proc.h:172
dlist_node * next
Definition: ilist.h:140

References Assert(), CleanUpLock(), dclist_delete_from_thoroughly(), dclist_is_empty(), LOCK::granted, lengthof, PGPROC::links, LOCK_LOCKMETHOD, LOCKBIT_OFF, LockMethods, dlist_node::next, LOCK::nGranted, LOCK::nRequested, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_WAITING, LOCK::requested, PGPROC::waitLock, PGPROC::waitLockMode, LOCK::waitMask, PGPROC::waitProcLock, LOCK::waitProcs, and PGPROC::waitStatus.

Referenced by CheckDeadLock(), and LockErrorCleanup().

◆ ResetAwaitedLock()

void ResetAwaitedLock ( void  )

Definition at line 1906 of file lock.c.

1907{
1908 awaitedLock = NULL;
1909}

References awaitedLock.

Referenced by LockErrorCleanup().

◆ VirtualXactLock()

bool VirtualXactLock ( VirtualTransactionId  vxid,
bool  wait 
)

Definition at line 4713 of file lock.c.

4714{
4715 LOCKTAG tag;
4716 PGPROC *proc;
4718
4720
4722 /* no vxid lock; localTransactionId is a normal, locked XID */
4723 return XactLockForVirtualXact(vxid, vxid.localTransactionId, wait);
4724
4726
4727 /*
4728 * If a lock table entry must be made, this is the PGPROC on whose behalf
4729 * it must be done. Note that the transaction might end or the PGPROC
4730 * might be reassigned to a new backend before we get around to examining
4731 * it, but it doesn't matter. If we find upon examination that the
4732 * relevant lxid is no longer running here, that's enough to prove that
4733 * it's no longer running anywhere.
4734 */
4735 proc = ProcNumberGetProc(vxid.procNumber);
4736 if (proc == NULL)
4737 return XactLockForVirtualXact(vxid, InvalidTransactionId, wait);
4738
4739 /*
4740 * We must acquire this lock before checking the procNumber and lxid
4741 * against the ones we're waiting for. The target backend will only set
4742 * or clear lxid while holding this lock.
4743 */
4745
4746 if (proc->vxid.procNumber != vxid.procNumber
4748 {
4749 /* VXID ended */
4750 LWLockRelease(&proc->fpInfoLock);
4751 return XactLockForVirtualXact(vxid, InvalidTransactionId, wait);
4752 }
4753
4754 /*
4755 * If we aren't asked to wait, there's no need to set up a lock table
4756 * entry. The transaction is still in progress, so just return false.
4757 */
4758 if (!wait)
4759 {
4760 LWLockRelease(&proc->fpInfoLock);
4761 return false;
4762 }
4763
4764 /*
4765 * OK, we're going to need to sleep on the VXID. But first, we must set
4766 * up the primary lock table entry, if needed (ie, convert the proc's
4767 * fast-path lock on its VXID to a regular lock).
4768 */
4769 if (proc->fpVXIDLock)
4770 {
4771 PROCLOCK *proclock;
4772 uint32 hashcode;
4773 LWLock *partitionLock;
4774
4775 hashcode = LockTagHashCode(&tag);
4776
4777 partitionLock = LockHashPartitionLock(hashcode);
4778 LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4779
4781 &tag, hashcode, ExclusiveLock);
4782 if (!proclock)
4783 {
4784 LWLockRelease(partitionLock);
4785 LWLockRelease(&proc->fpInfoLock);
4786 ereport(ERROR,
4787 (errcode(ERRCODE_OUT_OF_MEMORY),
4788 errmsg("out of shared memory"),
4789 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4790 }
4791 GrantLock(proclock->tag.myLock, proclock, ExclusiveLock);
4792
4793 LWLockRelease(partitionLock);
4794
4795 proc->fpVXIDLock = false;
4796 }
4797
4798 /*
4799 * If the proc has an XID now, we'll avoid a TwoPhaseGetXidByVirtualXID()
4800 * search. The proc might have assigned this XID but not yet locked it,
4801 * in which case the proc will lock this XID before releasing the VXID.
4802 * The fpInfoLock critical section excludes VirtualXactLockTableCleanup(),
4803 * so we won't save an XID of a different VXID. It doesn't matter whether
4804 * we save this before or after setting up the primary lock table entry.
4805 */
4806 xid = proc->xid;
4807
4808 /* Done with proc->fpLockBits */
4809 LWLockRelease(&proc->fpInfoLock);
4810
4811 /* Time to wait. */
4812 (void) LockAcquire(&tag, ShareLock, false, false);
4813
4814 LockRelease(&tag, ShareLock, false);
4815 return XactLockForVirtualXact(vxid, xid, wait);
4816}
static bool XactLockForVirtualXact(VirtualTransactionId vxid, TransactionId xid, bool wait)
Definition: lock.c:4662
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition: lock.c:808
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:2070
#define VirtualTransactionIdIsRecoveredPreparedXact(vxid)
Definition: lock.h:70
#define ShareLock
Definition: lockdefs.h:40
PGPROC * ProcNumberGetProc(ProcNumber procNumber)
Definition: procarray.c:3138
#define InvalidTransactionId
Definition: transam.h:31

References Assert(), DEFAULT_LOCKMETHOD, ereport, errcode(), errhint(), errmsg(), ERROR, ExclusiveLock, PGPROC::fpInfoLock, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, GrantLock(), InvalidTransactionId, VirtualTransactionId::localTransactionId, LockAcquire(), LockHashPartitionLock, LockMethods, LockRelease(), LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PROCLOCKTAG::myLock, VirtualTransactionId::procNumber, PGPROC::procNumber, ProcNumberGetProc(), SET_LOCKTAG_VIRTUALTRANSACTION, SetupLockInTable(), ShareLock, PROCLOCK::tag, VirtualTransactionIdIsRecoveredPreparedXact, VirtualTransactionIdIsValid, PGPROC::vxid, XactLockForVirtualXact(), and PGPROC::xid.

Referenced by ResolveRecoveryConflictWithVirtualXIDs(), WaitForLockersMultiple(), and WaitForOlderSnapshots().

◆ VirtualXactLockTableCleanup()

void VirtualXactLockTableCleanup ( void  )

Definition at line 4613 of file lock.c.

4614{
4615 bool fastpath;
4616 LocalTransactionId lxid;
4617
4619
4620 /*
4621 * Clean up shared memory state.
4622 */
4624
4625 fastpath = MyProc->fpVXIDLock;
4627 MyProc->fpVXIDLock = false;
4629
4631
4632 /*
4633 * If fpVXIDLock has been cleared without touching fpLocalTransactionId,
4634 * that means someone transferred the lock to the main lock table.
4635 */
4636 if (!fastpath && LocalTransactionIdIsValid(lxid))
4637 {
4639 LOCKTAG locktag;
4640
4641 vxid.procNumber = MyProcNumber;
4642 vxid.localTransactionId = lxid;
4643 SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid);
4644
4646 &locktag, ExclusiveLock, false);
4647 }
4648}
uint32 LocalTransactionId
Definition: c.h:625
ProcNumber MyProcNumber
Definition: globals.c:91
#define LocalTransactionIdIsValid(lxid)
Definition: lock.h:67

References Assert(), DEFAULT_LOCKMETHOD, ExclusiveLock, PGPROC::fpInfoLock, PGPROC::fpLocalTransactionId, PGPROC::fpVXIDLock, INVALID_PROC_NUMBER, InvalidLocalTransactionId, VirtualTransactionId::localTransactionId, LocalTransactionIdIsValid, LockMethods, LockRefindAndRelease(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, MyProcNumber, VirtualTransactionId::procNumber, PGPROC::procNumber, SET_LOCKTAG_VIRTUALTRANSACTION, and PGPROC::vxid.

Referenced by LockReleaseAll(), and ShutdownRecoveryTransactionEnvironment().

◆ VirtualXactLockTableInsert()

Variable Documentation

◆ LockTagTypeNames

PGDLLIMPORT const char* const LockTagTypeNames[]
extern

Definition at line 28 of file lockfuncs.c.

Referenced by GetLockNameFromTagType(), and pg_lock_status().

◆ log_lock_failure

PGDLLIMPORT bool log_lock_failure
extern

Definition at line 54 of file lock.c.

Referenced by heap_acquire_tuplock(), heap_lock_tuple(), and heapam_tuple_lock().

◆ max_locks_per_xact

PGDLLIMPORT int max_locks_per_xact
extern