PostgreSQL Source Code  git master
lock.c File Reference
#include "postgres.h"
#include <signal.h>
#include <unistd.h>
#include "access/transam.h"
#include "access/twophase.h"
#include "access/twophase_rmgr.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "pgstat.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/sinvaladt.h"
#include "storage/spin.h"
#include "storage/standby.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/resowner_private.h"
Include dependency graph for lock.c:

Go to the source code of this file.

Data Structures

struct  TwoPhaseLockRecord
 
struct  FastPathStrongRelationLockData
 

Macros

#define NLOCKENTS()   mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
 
#define FAST_PATH_BITS_PER_SLOT   3
 
#define FAST_PATH_LOCKNUMBER_OFFSET   1
 
#define FAST_PATH_MASK   ((1 << FAST_PATH_BITS_PER_SLOT) - 1)
 
#define FAST_PATH_GET_BITS(proc, n)   (((proc)->fpLockBits >> (FAST_PATH_BITS_PER_SLOT * n)) & FAST_PATH_MASK)
 
#define FAST_PATH_BIT_POSITION(n, l)
 
#define FAST_PATH_SET_LOCKMODE(proc, n, l)   (proc)->fpLockBits |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)
 
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)   (proc)->fpLockBits &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))
 
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)   ((proc)->fpLockBits & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))
 
#define EligibleForRelationFastPath(locktag, mode)
 
#define ConflictsWithRelationFastPath(locktag, mode)
 
#define FAST_PATH_STRONG_LOCK_HASH_BITS   10
 
#define FAST_PATH_STRONG_LOCK_HASH_PARTITIONS   (1 << FAST_PATH_STRONG_LOCK_HASH_BITS)
 
#define FastPathStrongLockHashPartition(hashcode)   ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS)
 
#define LOCK_PRINT(where, lock, type)   ((void) 0)
 
#define PROCLOCK_PRINT(where, proclockP)   ((void) 0)
 

Typedefs

typedef struct TwoPhaseLockRecord TwoPhaseLockRecord
 

Functions

static bool FastPathGrantRelationLock (Oid relid, LOCKMODE lockmode)
 
static bool FastPathUnGrantRelationLock (Oid relid, LOCKMODE lockmode)
 
static bool FastPathTransferRelationLocks (LockMethod lockMethodTable, const LOCKTAG *locktag, uint32 hashcode)
 
static PROCLOCKFastPathGetRelationLockEntry (LOCALLOCK *locallock)
 
static uint32 proclock_hash (const void *key, Size keysize)
 
static void RemoveLocalLock (LOCALLOCK *locallock)
 
static PROCLOCKSetupLockInTable (LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
 
static void GrantLockLocal (LOCALLOCK *locallock, ResourceOwner owner)
 
static void BeginStrongLockAcquire (LOCALLOCK *locallock, uint32 fasthashcode)
 
static void FinishStrongLockAcquire (void)
 
static void WaitOnLock (LOCALLOCK *locallock, ResourceOwner owner)
 
static void ReleaseLockIfHeld (LOCALLOCK *locallock, bool sessionLock)
 
static void LockReassignOwner (LOCALLOCK *locallock, ResourceOwner parent)
 
static bool UnGrantLock (LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
 
static void CleanUpLock (LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
 
static void LockRefindAndRelease (LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
 
static void GetSingleProcBlockerStatusData (PGPROC *blocked_proc, BlockedProcsData *data)
 
void InitLocks (void)
 
LockMethod GetLocksMethodTable (const LOCK *lock)
 
LockMethod GetLockTagsMethodTable (const LOCKTAG *locktag)
 
uint32 LockTagHashCode (const LOCKTAG *locktag)
 
static uint32 ProcLockHashCode (const PROCLOCKTAG *proclocktag, uint32 hashcode)
 
bool DoLockModesConflict (LOCKMODE mode1, LOCKMODE mode2)
 
bool LockHeldByMe (const LOCKTAG *locktag, LOCKMODE lockmode)
 
bool LockHasWaiters (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
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)
 
static void CheckAndSetLockHeld (LOCALLOCK *locallock, bool acquired)
 
bool LockCheckConflicts (LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
 
void GrantLock (LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
 
void AbortStrongLockAcquire (void)
 
void GrantAwaitedLock (void)
 
void MarkLockClear (LOCALLOCK *locallock)
 
void RemoveFromWaitQueue (PGPROC *proc, uint32 hashcode)
 
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)
 
VirtualTransactionIdGetLockConflicts (const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
 
void AtPrepare_Locks (void)
 
void PostPrepare_Locks (TransactionId xid)
 
Size LockShmemSize (void)
 
LockDataGetLockStatusData (void)
 
BlockedProcsDataGetBlockerStatusData (int blocked_pid)
 
xl_standby_lockGetRunningTransactionLocks (int *nlocks)
 
const char * GetLockmodeName (LOCKMETHODID lockmethodid, LOCKMODE mode)
 
void lock_twophase_recover (TransactionId xid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_standby_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 VirtualXactLockTableInsert (VirtualTransactionId vxid)
 
void VirtualXactLockTableCleanup (void)
 
bool VirtualXactLock (VirtualTransactionId vxid, bool wait)
 
int LockWaiterCount (const LOCKTAG *locktag)
 

Variables

int max_locks_per_xact
 
static const LOCKMASK LockConflicts []
 
static const char *const lock_mode_names []
 
static bool Dummy_trace = false
 
static const LockMethodData default_lockmethod
 
static const LockMethodData user_lockmethod
 
static const LockMethod LockMethods []
 
static int FastPathLocalUseCount = 0
 
static bool IsRelationExtensionLockHeld PG_USED_FOR_ASSERTS_ONLY = false
 
static volatile FastPathStrongRelationLockDataFastPathStrongRelationLocks
 
static HTABLockMethodLockHash
 
static HTABLockMethodProcLockHash
 
static HTABLockMethodLocalHash
 
static LOCALLOCKStrongLockInProgress
 
static LOCALLOCKawaitedLock
 
static ResourceOwner awaitedOwner
 

Macro Definition Documentation

◆ ConflictsWithRelationFastPath

#define ConflictsWithRelationFastPath (   locktag,
  mode 
)
Value:
((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
(locktag)->locktag_type == LOCKTAG_RELATION && \
(locktag)->locktag_field1 != InvalidOid && \
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
#define InvalidOid
Definition: postgres_ext.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39

Definition at line 232 of file lock.c.

Referenced by GetLockConflicts(), lock_twophase_recover(), LockAcquireExtended(), and LockRefindAndRelease().

◆ EligibleForRelationFastPath

#define EligibleForRelationFastPath (   locktag,
  mode 
)
Value:
((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
(locktag)->locktag_type == LOCKTAG_RELATION && \
(locktag)->locktag_field1 == MyDatabaseId && \
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
Oid MyDatabaseId
Definition: globals.c:85
#define InvalidOid
Definition: postgres_ext.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39

Definition at line 226 of file lock.c.

Referenced by LockAcquireExtended(), LockRelease(), and LockReleaseAll().

◆ FAST_PATH_BIT_POSITION

#define FAST_PATH_BIT_POSITION (   n,
 
)
Value:
AssertMacro((n) < FP_LOCK_SLOTS_PER_BACKEND), \
#define AssertMacro(condition)
Definition: c.h:746
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:202
#define FAST_PATH_BITS_PER_SLOT
Definition: lock.c:201

Definition at line 206 of file lock.c.

◆ FAST_PATH_BITS_PER_SLOT

#define FAST_PATH_BITS_PER_SLOT   3

Definition at line 201 of file lock.c.

Referenced by FastPathTransferRelationLocks().

◆ FAST_PATH_CHECK_LOCKMODE

#define FAST_PATH_CHECK_LOCKMODE (   proc,
  n,
 
)    ((proc)->fpLockBits & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))

◆ FAST_PATH_CLEAR_LOCKMODE

#define FAST_PATH_CLEAR_LOCKMODE (   proc,
  n,
 
)    (proc)->fpLockBits &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))

◆ FAST_PATH_GET_BITS

#define FAST_PATH_GET_BITS (   proc,
 
)    (((proc)->fpLockBits >> (FAST_PATH_BITS_PER_SLOT * n)) & FAST_PATH_MASK)

◆ FAST_PATH_LOCKNUMBER_OFFSET

#define FAST_PATH_LOCKNUMBER_OFFSET   1

Definition at line 202 of file lock.c.

Referenced by FastPathTransferRelationLocks(), GetLockConflicts(), and GetLockStatusData().

◆ FAST_PATH_MASK

#define FAST_PATH_MASK   ((1 << FAST_PATH_BITS_PER_SLOT) - 1)

Definition at line 203 of file lock.c.

◆ FAST_PATH_SET_LOCKMODE

#define FAST_PATH_SET_LOCKMODE (   proc,
  n,
 
)    (proc)->fpLockBits |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)

Definition at line 211 of file lock.c.

Referenced by FastPathGrantRelationLock().

◆ FAST_PATH_STRONG_LOCK_HASH_BITS

#define FAST_PATH_STRONG_LOCK_HASH_BITS   10

Definition at line 259 of file lock.c.

◆ FAST_PATH_STRONG_LOCK_HASH_PARTITIONS

#define FAST_PATH_STRONG_LOCK_HASH_PARTITIONS   (1 << FAST_PATH_STRONG_LOCK_HASH_BITS)

Definition at line 260 of file lock.c.

◆ FastPathStrongLockHashPartition

#define FastPathStrongLockHashPartition (   hashcode)    ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS)

◆ LOCK_PRINT

#define LOCK_PRINT (   where,
  lock,
  type 
)    ((void) 0)

◆ NLOCKENTS

Definition at line 56 of file lock.c.

Referenced by InitLocks(), and LockShmemSize().

◆ PROCLOCK_PRINT

Typedef Documentation

◆ TwoPhaseLockRecord

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )

Definition at line 1757 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

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

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

Definition at line 3230 of file lock.c.

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

Referenced by PrepareTransaction().

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

◆ BeginStrongLockAcquire()

static void BeginStrongLockAcquire ( LOCALLOCK locallock,
uint32  fasthashcode 
)
static

Definition at line 1721 of file lock.c.

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

Referenced by LockAcquireExtended().

1722 {
1723  Assert(StrongLockInProgress == NULL);
1724  Assert(locallock->holdsStrongLockCount == false);
1725 
1726  /*
1727  * Adding to a memory location is not atomic, so we take a spinlock to
1728  * ensure we don't collide with someone else trying to bump the count at
1729  * the same time.
1730  *
1731  * XXX: It might be worth considering using an atomic fetch-and-add
1732  * instruction here, on architectures where that is supported.
1733  */
1734 
1736  FastPathStrongRelationLocks->count[fasthashcode]++;
1737  locallock->holdsStrongLockCount = true;
1738  StrongLockInProgress = locallock;
1740 }
bool holdsStrongLockCount
Definition: lock.h:418
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:268
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:286
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745

◆ CheckAndSetLockHeld()

static void CheckAndSetLockHeld ( LOCALLOCK locallock,
bool  acquired 
)
inlinestatic

Definition at line 1352 of file lock.c.

References LOCALLOCK_LOCKTAG, LOCKTAG_PAGE, and LOCKTAG_RELATION_EXTEND.

Referenced by GrantLockLocal(), and RemoveLocalLock().

1353 {
1354 #ifdef USE_ASSERT_CHECKING
1355  if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_RELATION_EXTEND)
1356  IsRelationExtensionLockHeld = acquired;
1357  else if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_PAGE)
1358  IsPageLockHeld = acquired;
1359 
1360 #endif
1361 }
#define LOCALLOCK_LOCKTAG(llock)
Definition: lock.h:423

◆ CleanUpLock()

static void CleanUpLock ( LOCK lock,
PROCLOCK proclock,
LockMethod  lockMethodTable,
uint32  hashcode,
bool  wakeupNeeded 
)
static

Definition at line 1635 of file lock.c.

References Assert, elog, HASH_REMOVE, hash_search_with_hash_value(), PROCLOCK::holdMask, LOCK_PRINT, PROCLOCK::lockLink, LOCK::nRequested, PANIC, PROCLOCK::procLink, PROCLOCK_PRINT, ProcLockHashCode(), LOCK::procLocks, ProcLockWakeup(), SHMQueueDelete(), SHMQueueEmpty(), LOCK::tag, and PROCLOCK::tag.

Referenced by LockRefindAndRelease(), LockRelease(), LockReleaseAll(), and RemoveFromWaitQueue().

1638 {
1639  /*
1640  * If this was my last hold on this lock, delete my entry in the proclock
1641  * table.
1642  */
1643  if (proclock->holdMask == 0)
1644  {
1645  uint32 proclock_hashcode;
1646 
1647  PROCLOCK_PRINT("CleanUpLock: deleting", proclock);
1648  SHMQueueDelete(&proclock->lockLink);
1649  SHMQueueDelete(&proclock->procLink);
1650  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
1652  (void *) &(proclock->tag),
1653  proclock_hashcode,
1654  HASH_REMOVE,
1655  NULL))
1656  elog(PANIC, "proclock table corrupted");
1657  }
1658 
1659  if (lock->nRequested == 0)
1660  {
1661  /*
1662  * The caller just released the last lock, so garbage-collect the lock
1663  * object.
1664  */
1665  LOCK_PRINT("CleanUpLock: deleting", lock, 0);
1666  Assert(SHMQueueEmpty(&(lock->procLocks)));
1668  (void *) &(lock->tag),
1669  hashcode,
1670  HASH_REMOVE,
1671  NULL))
1672  elog(PANIC, "lock table corrupted");
1673  }
1674  else if (wakeupNeeded)
1675  {
1676  /* There are waiters on this lock, so wake them up. */
1677  ProcLockWakeup(lockMethodTable, lock);
1678  }
1679 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:940
PROCLOCKTAG tag
Definition: lock.h:351
int nRequested
Definition: lock.h:298
LOCKMASK holdMask
Definition: lock.h:355
LOCKTAG tag
Definition: lock.h:290
SHM_QUEUE lockLink
Definition: lock.h:357
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define PANIC
Definition: elog.h:53
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:565
unsigned int uint32
Definition: c.h:374
SHM_QUEUE procLocks
Definition: lock.h:295
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1632
SHM_QUEUE procLink
Definition: lock.h:358
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define Assert(condition)
Definition: c.h:745
static HTAB * LockMethodLockHash
Definition: lock.c:280
#define elog(elevel,...)
Definition: elog.h:214
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 583 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

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

◆ FastPathGetRelationLockEntry()

static PROCLOCK * FastPathGetRelationLockEntry ( LOCALLOCK locallock)
static

Definition at line 2810 of file lock.c.

References DEFAULT_LOCKMETHOD, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FAST_PATH_CHECK_LOCKMODE, FAST_PATH_CLEAR_LOCKMODE, FAST_PATH_GET_BITS, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpInfoLock, PGPROC::fpRelId, GrantLock(), HASH_FIND, hash_search_with_hash_value(), LOCALLOCK::hashcode, LOCALLOCKTAG::lock, LockHashPartitionLock, TwoPhaseLockRecord::lockmode, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field2, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, ProcLockHashCode(), SetupLockInTable(), PROCLOCK::tag, and LOCALLOCK::tag.

Referenced by AtPrepare_Locks().

2811 {
2812  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
2813  LOCKTAG *locktag = &locallock->tag.lock;
2814  PROCLOCK *proclock = NULL;
2815  LWLock *partitionLock = LockHashPartitionLock(locallock->hashcode);
2816  Oid relid = locktag->locktag_field2;
2817  uint32 f;
2818 
2820 
2821  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2822  {
2823  uint32 lockmode;
2824 
2825  /* Look for an allocated slot matching the given relid. */
2826  if (relid != MyProc->fpRelId[f] || FAST_PATH_GET_BITS(MyProc, f) == 0)
2827  continue;
2828 
2829  /* If we don't have a lock of the given mode, forget it! */
2830  lockmode = locallock->tag.mode;
2831  if (!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2832  break;
2833 
2834  /* Find or create lock object. */
2835  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2836 
2837  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
2838  locallock->hashcode, lockmode);
2839  if (!proclock)
2840  {
2841  LWLockRelease(partitionLock);
2843  ereport(ERROR,
2844  (errcode(ERRCODE_OUT_OF_MEMORY),
2845  errmsg("out of shared memory"),
2846  errhint("You might need to increase max_locks_per_transaction.")));
2847  }
2848  GrantLock(proclock->tag.myLock, proclock, lockmode);
2849  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2850 
2851  LWLockRelease(partitionLock);
2852 
2853  /* No need to examine remaining slots. */
2854  break;
2855  }
2856 
2858 
2859  /* Lock may have already been transferred by some other backend. */
2860  if (proclock == NULL)
2861  {
2862  LOCK *lock;
2863  PROCLOCKTAG proclocktag;
2864  uint32 proclock_hashcode;
2865 
2866  LWLockAcquire(partitionLock, LW_SHARED);
2867 
2869  (void *) locktag,
2870  locallock->hashcode,
2871  HASH_FIND,
2872  NULL);
2873  if (!lock)
2874  elog(ERROR, "failed to re-find shared lock object");
2875 
2876  proclocktag.myLock = lock;
2877  proclocktag.myProc = MyProc;
2878 
2879  proclock_hashcode = ProcLockHashCode(&proclocktag, locallock->hashcode);
2880  proclock = (PROCLOCK *)
2882  (void *) &proclocktag,
2883  proclock_hashcode,
2884  HASH_FIND,
2885  NULL);
2886  if (!proclock)
2887  elog(ERROR, "failed to re-find shared proclock object");
2888  LWLockRelease(partitionLock);
2889  }
2890 
2891  return proclock;
2892 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:940
PROCLOCKTAG tag
Definition: lock.h:351
uint32 hashcode
Definition: lock.h:411
Definition: lwlock.h:31
LOCALLOCKTAG tag
Definition: lock.h:408
int errhint(const char *fmt,...)
Definition: elog.c:1071
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1170
LOCKTAG lock
Definition: lock.h:389
LOCKMODE mode
Definition: lock.h:390
PGPROC * MyProc
Definition: proc.c:67
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1555
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
Definition: lock.h:163
#define LockHashPartitionLock(hashcode)
Definition: lock.h:504
int errcode(int sqlerrcode)
Definition: elog.c:610
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
unsigned int Oid
Definition: postgres_ext.h:31
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:215
#define ERROR
Definition: elog.h:43
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:565
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
uint32 locktag_field2
Definition: lock.h:166
unsigned int uint32
Definition: c.h:374
Definition: lock.h:287
#define ereport(elevel,...)
Definition: elog.h:144
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:200
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
PGPROC * myProc
Definition: lock.h:345
Definition: lock.h:348
int errmsg(const char *fmt,...)
Definition: elog.c:824
#define elog(elevel,...)
Definition: elog.h:214
LOCK * myLock
Definition: lock.h:344
static const LockMethod LockMethods[]
Definition: lock.c:150
LWLock fpInfoLock
Definition: proc.h:198
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:213

◆ FastPathGrantRelationLock()

static bool FastPathGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

Definition at line 2655 of file lock.c.

References Assert, FAST_PATH_CHECK_LOCKMODE, FAST_PATH_GET_BITS, FAST_PATH_SET_LOCKMODE, FastPathLocalUseCount, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpRelId, and MyProc.

Referenced by LockAcquireExtended().

2656 {
2657  uint32 f;
2658  uint32 unused_slot = FP_LOCK_SLOTS_PER_BACKEND;
2659 
2660  /* Scan for existing entry for this relid, remembering empty slot. */
2661  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2662  {
2663  if (FAST_PATH_GET_BITS(MyProc, f) == 0)
2664  unused_slot = f;
2665  else if (MyProc->fpRelId[f] == relid)
2666  {
2667  Assert(!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode));
2668  FAST_PATH_SET_LOCKMODE(MyProc, f, lockmode);
2669  return true;
2670  }
2671  }
2672 
2673  /* If no existing entry, use any empty slot. */
2674  if (unused_slot < FP_LOCK_SLOTS_PER_BACKEND)
2675  {
2676  MyProc->fpRelId[unused_slot] = relid;
2677  FAST_PATH_SET_LOCKMODE(MyProc, unused_slot, lockmode);
2679  return true;
2680  }
2681 
2682  /* No existing entry, and no empty slot. */
2683  return false;
2684 }
PGPROC * MyProc
Definition: proc.c:67
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
static int FastPathLocalUseCount
Definition: lock.c:171
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:215
#define FAST_PATH_SET_LOCKMODE(proc, n, l)
Definition: lock.c:211
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
unsigned int uint32
Definition: c.h:374
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:200
#define Assert(condition)
Definition: c.h:745

◆ FastPathTransferRelationLocks()

static bool FastPathTransferRelationLocks ( LockMethod  lockMethodTable,
const LOCKTAG locktag,
uint32  hashcode 
)
static

Definition at line 2722 of file lock.c.

References PROC_HDR::allProcCount, PROC_HDR::allProcs, PGPROC::databaseId, FAST_PATH_BITS_PER_SLOT, FAST_PATH_CHECK_LOCKMODE, FAST_PATH_CLEAR_LOCKMODE, FAST_PATH_GET_BITS, FAST_PATH_LOCKNUMBER_OFFSET, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpInfoLock, PGPROC::fpRelId, GrantLock(), i, LockHashPartitionLock, TwoPhaseLockRecord::lockmode, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PROCLOCKTAG::myLock, ProcGlobal, SetupLockInTable(), and PROCLOCK::tag.

Referenced by LockAcquireExtended().

2724 {
2725  LWLock *partitionLock = LockHashPartitionLock(hashcode);
2726  Oid relid = locktag->locktag_field2;
2727  uint32 i;
2728 
2729  /*
2730  * Every PGPROC that can potentially hold a fast-path lock is present in
2731  * ProcGlobal->allProcs. Prepared transactions are not, but any
2732  * outstanding fast-path locks held by prepared transactions are
2733  * transferred to the main lock table.
2734  */
2735  for (i = 0; i < ProcGlobal->allProcCount; i++)
2736  {
2737  PGPROC *proc = &ProcGlobal->allProcs[i];
2738  uint32 f;
2739 
2741 
2742  /*
2743  * If the target backend isn't referencing the same database as the
2744  * lock, then we needn't examine the individual relation IDs at all;
2745  * none of them can be relevant.
2746  *
2747  * proc->databaseId is set at backend startup time and never changes
2748  * thereafter, so it might be safe to perform this test before
2749  * acquiring &proc->fpInfoLock. In particular, it's certainly safe to
2750  * assume that if the target backend holds any fast-path locks, it
2751  * must have performed a memory-fencing operation (in particular, an
2752  * LWLock acquisition) since setting proc->databaseId. However, it's
2753  * less clear that our backend is certain to have performed a memory
2754  * fencing operation since the other backend set proc->databaseId. So
2755  * for now, we test it after acquiring the LWLock just to be safe.
2756  */
2757  if (proc->databaseId != locktag->locktag_field1)
2758  {
2759  LWLockRelease(&proc->fpInfoLock);
2760  continue;
2761  }
2762 
2763  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2764  {
2765  uint32 lockmode;
2766 
2767  /* Look for an allocated slot matching the given relid. */
2768  if (relid != proc->fpRelId[f] || FAST_PATH_GET_BITS(proc, f) == 0)
2769  continue;
2770 
2771  /* Find or create lock object. */
2772  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2773  for (lockmode = FAST_PATH_LOCKNUMBER_OFFSET;
2775  ++lockmode)
2776  {
2777  PROCLOCK *proclock;
2778 
2779  if (!FAST_PATH_CHECK_LOCKMODE(proc, f, lockmode))
2780  continue;
2781  proclock = SetupLockInTable(lockMethodTable, proc, locktag,
2782  hashcode, lockmode);
2783  if (!proclock)
2784  {
2785  LWLockRelease(partitionLock);
2786  LWLockRelease(&proc->fpInfoLock);
2787  return false;
2788  }
2789  GrantLock(proclock->tag.myLock, proclock, lockmode);
2790  FAST_PATH_CLEAR_LOCKMODE(proc, f, lockmode);
2791  }
2792  LWLockRelease(partitionLock);
2793 
2794  /* No need to examine remaining slots. */
2795  break;
2796  }
2797  LWLockRelease(&proc->fpInfoLock);
2798  }
2799  return true;
2800 }
PROCLOCKTAG tag
Definition: lock.h:351
Definition: lwlock.h:31
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1170
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1555
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
#define LockHashPartitionLock(hashcode)
Definition: lock.h:504
PROC_HDR * ProcGlobal
Definition: proc.c:80
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:215
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
uint32 locktag_field2
Definition: lock.h:166
Oid databaseId
Definition: proc.h:120
unsigned int uint32
Definition: c.h:374
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:200
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint32 allProcCount
Definition: proc.h:255
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:202
Definition: lock.h:348
int i
LOCK * myLock
Definition: lock.h:344
PGPROC * allProcs
Definition: proc.h:251
LWLock fpInfoLock
Definition: proc.h:198
#define FAST_PATH_BITS_PER_SLOT
Definition: lock.c:201
uint32 locktag_field1
Definition: lock.h:165
Definition: proc.h:101
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:213

◆ FastPathUnGrantRelationLock()

static bool FastPathUnGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

Definition at line 2692 of file lock.c.

References Assert, FAST_PATH_CHECK_LOCKMODE, FAST_PATH_CLEAR_LOCKMODE, FAST_PATH_GET_BITS, FastPathLocalUseCount, FP_LOCK_SLOTS_PER_BACKEND, PGPROC::fpRelId, and MyProc.

Referenced by LockRelease(), and LockReleaseAll().

2693 {
2694  uint32 f;
2695  bool result = false;
2696 
2698  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2699  {
2700  if (MyProc->fpRelId[f] == relid
2701  && FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2702  {
2703  Assert(!result);
2704  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2705  result = true;
2706  /* we continue iterating so as to update FastPathLocalUseCount */
2707  }
2708  if (FAST_PATH_GET_BITS(MyProc, f) != 0)
2710  }
2711  return result;
2712 }
PGPROC * MyProc
Definition: proc.c:67
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
static int FastPathLocalUseCount
Definition: lock.c:171
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:215
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
unsigned int uint32
Definition: c.h:374
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:200
#define Assert(condition)
Definition: c.h:745
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:213

◆ FinishStrongLockAcquire()

static void FinishStrongLockAcquire ( void  )
static

Definition at line 1747 of file lock.c.

Referenced by LockAcquireExtended().

1748 {
1749  StrongLockInProgress = NULL;
1750 }
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:286

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

Definition at line 3753 of file lock.c.

References Assert, BackendPidGetProcWithLock(), dlist_iter::cur, dlist_container, dlist_foreach, GetSingleProcBlockerStatusData(), i, PGPROC::lockGroupLeader, PGPROC::lockGroupMembers, LockHashPartitionLockByIndex, BlockedProcsData::locks, LW_SHARED, LWLockAcquire(), LWLockRelease(), MaxBackends, BlockedProcsData::maxlocks, BlockedProcsData::maxpids, BlockedProcsData::maxprocs, BlockedProcsData::nlocks, BlockedProcsData::npids, BlockedProcsData::nprocs, NUM_LOCK_PARTITIONS, palloc(), BlockedProcsData::procs, and BlockedProcsData::waiter_pids.

Referenced by pg_blocking_pids().

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

◆ GetLockConflicts()

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

Definition at line 2912 of file lock.c.

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

Referenced by ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

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

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

Definition at line 4016 of file lock.c.

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

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

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

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)

Definition at line 487 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

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

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

Definition at line 3569 of file lock.c.

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

Referenced by pg_lock_status().

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

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 499 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

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

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

Definition at line 3933 of file lock.c.

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

Referenced by LogStandbySnapshot().

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

◆ GetSingleProcBlockerStatusData()

static void GetSingleProcBlockerStatusData ( PGPROC blocked_proc,
BlockedProcsData data 
)
static

Definition at line 3833 of file lock.c.

References LockInstanceData::backend, PGPROC::backendId, LockInstanceData::fastpath, BlockedProcData::first_lock, BlockedProcData::first_waiter, PROCLOCK::groupLeader, PROCLOCK::holdMask, LockInstanceData::holdMask, i, LockInstanceData::leaderPid, PROC_QUEUE::links, PGPROC::links, PROCLOCK::lockLink, BlockedProcsData::locks, LockInstanceData::locktag, PGPROC::lxid, LockInstanceData::lxid, Max, MaxBackends, BlockedProcsData::maxlocks, BlockedProcsData::maxpids, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, SHM_QUEUE::next, BlockedProcsData::nlocks, NoLock, BlockedProcsData::npids, BlockedProcsData::nprocs, BlockedProcData::num_locks, BlockedProcData::num_waiters, offsetof, PGPROC::pid, LockInstanceData::pid, BlockedProcData::pid, LOCK::procLocks, BlockedProcsData::procs, repalloc(), SHMQueueNext(), PROC_QUEUE::size, LOCK::tag, PROCLOCK::tag, BlockedProcsData::waiter_pids, PGPROC::waitLock, PGPROC::waitLockMode, LockInstanceData::waitLockMode, and LOCK::waitProcs.

Referenced by GetBlockerStatusData().

3834 {
3835  LOCK *theLock = blocked_proc->waitLock;
3836  BlockedProcData *bproc;
3837  SHM_QUEUE *procLocks;
3838  PROCLOCK *proclock;
3839  PROC_QUEUE *waitQueue;
3840  PGPROC *proc;
3841  int queue_size;
3842  int i;
3843 
3844  /* Nothing to do if this proc is not blocked */
3845  if (theLock == NULL)
3846  return;
3847 
3848  /* Set up a procs[] element */
3849  bproc = &data->procs[data->nprocs++];
3850  bproc->pid = blocked_proc->pid;
3851  bproc->first_lock = data->nlocks;
3852  bproc->first_waiter = data->npids;
3853 
3854  /*
3855  * We may ignore the proc's fast-path arrays, since nothing in those could
3856  * be related to a contended lock.
3857  */
3858 
3859  /* Collect all PROCLOCKs associated with theLock */
3860  procLocks = &(theLock->procLocks);
3861  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3862  offsetof(PROCLOCK, lockLink));
3863  while (proclock)
3864  {
3865  PGPROC *proc = proclock->tag.myProc;
3866  LOCK *lock = proclock->tag.myLock;
3867  LockInstanceData *instance;
3868 
3869  if (data->nlocks >= data->maxlocks)
3870  {
3871  data->maxlocks += MaxBackends;
3872  data->locks = (LockInstanceData *)
3873  repalloc(data->locks, sizeof(LockInstanceData) * data->maxlocks);
3874  }
3875 
3876  instance = &data->locks[data->nlocks];
3877  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3878  instance->holdMask = proclock->holdMask;
3879  if (proc->waitLock == lock)
3880  instance->waitLockMode = proc->waitLockMode;
3881  else
3882  instance->waitLockMode = NoLock;
3883  instance->backend = proc->backendId;
3884  instance->lxid = proc->lxid;
3885  instance->pid = proc->pid;
3886  instance->leaderPid = proclock->groupLeader->pid;
3887  instance->fastpath = false;
3888  data->nlocks++;
3889 
3890  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3891  offsetof(PROCLOCK, lockLink));
3892  }
3893 
3894  /* Enlarge waiter_pids[] if it's too small to hold all wait queue PIDs */
3895  waitQueue = &(theLock->waitProcs);
3896  queue_size = waitQueue->size;
3897 
3898  if (queue_size > data->maxpids - data->npids)
3899  {
3900  data->maxpids = Max(data->maxpids + MaxBackends,
3901  data->npids + queue_size);
3902  data->waiter_pids = (int *) repalloc(data->waiter_pids,
3903  sizeof(int) * data->maxpids);
3904  }
3905 
3906  /* Collect PIDs from the lock's wait queue, stopping at blocked_proc */
3907  proc = (PGPROC *) waitQueue->links.next;
3908  for (i = 0; i < queue_size; i++)
3909  {
3910  if (proc == blocked_proc)
3911  break;
3912  data->waiter_pids[data->npids++] = proc->pid;
3913  proc = (PGPROC *) proc->links.next;
3914  }
3915 
3916  bproc->num_locks = data->nlocks - bproc->first_lock;
3917  bproc->num_waiters = data->npids - bproc->first_waiter;
3918 }
PROCLOCKTAG tag
Definition: lock.h:351
int * waiter_pids
Definition: lock.h:466
BackendId backendId
Definition: proc.h:119
int first_lock
Definition: lock.h:454
SHM_QUEUE links
Definition: lock.h:31
int num_waiters
Definition: lock.h:459
LOCKMASK holdMask
Definition: lock.h:355
SHM_QUEUE links
Definition: proc.h:104
struct SHM_QUEUE * next
Definition: shmem.h:31
bool fastpath
Definition: lock.h:440
LOCKMODE waitLockMode
Definition: proc.h:147
LOCKTAG tag
Definition: lock.h:290
Definition: lock.h:163
SHM_QUEUE lockLink
Definition: lock.h:357
BlockedProcData * procs
Definition: lock.h:464
LOCKTAG locktag
Definition: lock.h:433
LOCKMODE waitLockMode
Definition: lock.h:435
int num_locks
Definition: lock.h:455
PROC_QUEUE waitProcs
Definition: lock.h:296
int leaderPid
Definition: lock.h:439
int MaxBackends
Definition: globals.c:136
#define NoLock
Definition: lockdefs.h:34
Definition: lock.h:287
LOCK * waitLock
Definition: proc.h:145
int maxlocks
Definition: lock.h:470
SHM_QUEUE procLocks
Definition: lock.h:295
LockInstanceData * locks
Definition: lock.h:465
BackendId backend
Definition: lock.h:436
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
int first_waiter
Definition: lock.h:458
#define Max(x, y)
Definition: c.h:921
LocalTransactionId lxid
Definition: lock.h:437
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
LOCKMASK holdMask
Definition: lock.h:434
PGPROC * myProc
Definition: lock.h:345
Definition: lock.h:348
int i
int size
Definition: lock.h:32
LOCK * myLock
Definition: lock.h:344
Definition: proc.h:101
int pid
Definition: proc.h:115
#define offsetof(type, field)
Definition: c.h:668
PGPROC * groupLeader
Definition: lock.h:354
LocalTransactionId lxid
Definition: proc.h:112

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1786 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

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

◆ GrantLock()

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

Definition at line 1555 of file lock.c.

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

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

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

◆ GrantLockLocal()

static void GrantLockLocal ( LOCALLOCK locallock,
ResourceOwner  owner 
)
static

Definition at line 1689 of file lock.c.

References Assert, CheckAndSetLockHeld(), i, LOCALLOCK::lockOwners, LOCALLOCK::maxLockOwners, LOCALLOCKOWNER::nLocks, LOCALLOCK::nLocks, LOCALLOCK::numLockOwners, LOCALLOCKOWNER::owner, and ResourceOwnerRememberLock().

Referenced by GrantAwaitedLock(), and LockAcquireExtended().

1690 {
1691  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1692  int i;
1693 
1694  Assert(locallock->numLockOwners < locallock->maxLockOwners);
1695  /* Count the total */
1696  locallock->nLocks++;
1697  /* Count the per-owner lock */
1698  for (i = 0; i < locallock->numLockOwners; i++)
1699  {
1700  if (lockOwners[i].owner == owner)
1701  {
1702  lockOwners[i].nLocks++;
1703  return;
1704  }
1705  }
1706  lockOwners[i].owner = owner;
1707  lockOwners[i].nLocks = 1;
1708  locallock->numLockOwners++;
1709  if (owner != NULL)
1710  ResourceOwnerRememberLock(owner, locallock);
1711 
1712  /* Indicate that the lock is acquired for certain types of locks. */
1713  CheckAndSetLockHeld(locallock, true);
1714 }
int numLockOwners
Definition: lock.h:415
int64 nLocks
Definition: lock.h:402
int maxLockOwners
Definition: lock.h:416
static void CheckAndSetLockHeld(LOCALLOCK *locallock, bool acquired)
Definition: lock.c:1352
#define Assert(condition)
Definition: c.h:745
LOCALLOCKOWNER * lockOwners
Definition: lock.h:417
int64 nLocks
Definition: lock.h:414
int i
struct ResourceOwnerData * owner
Definition: lock.h:401
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:957

◆ InitLocks()

void InitLocks ( void  )

Definition at line 404 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ lock_twophase_postabort()

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

Definition at line 4368 of file lock.c.

References lock_twophase_postcommit().

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

◆ lock_twophase_postcommit()

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

Definition at line 4342 of file lock.c.

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

Referenced by lock_twophase_postabort().

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

◆ lock_twophase_recover()

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

Definition at line 4129 of file lock.c.

References Assert, ConflictsWithRelationFastPath, FastPathStrongRelationLockData::count, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FastPathStrongLockHashPartition, LOCK::granted, GrantLock(), LOCK::grantMask, PROCLOCK::groupLeader, HASH_ENTER_NULL, HASH_REMOVE, hash_search_with_hash_value(), PROCLOCK::holdMask, lengthof, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartition, LockHashPartitionLock, PROCLOCK::lockLink, TwoPhaseLockRecord::lockmode, LockMethodData::lockModeNames, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_field3, LOCKTAG::locktag_lockmethodid, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MAX_LOCKMODES, MemSet, FastPathStrongRelationLockData::mutex, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCK::nRequested, PANIC, PROCLOCK::procLink, PROCLOCK_PRINT, ProcLockHashCode(), LOCK::procLocks, ProcQueueInit(), PROCLOCK::releaseMask, LOCK::requested, SHMQueueEmpty(), SHMQueueInit(), SHMQueueInsertBefore(), SpinLockAcquire, SpinLockRelease, LOCK::tag, TwoPhaseGetDummyProc(), LOCK::waitMask, and LOCK::waitProcs.

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

◆ lock_twophase_standby_recover()

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

Definition at line 4310 of file lock.c.

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

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

◆ LockAcquire()

◆ LockAcquireExtended()

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

Definition at line 771 of file lock.c.

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

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

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

◆ LockCheckConflicts()

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

Definition at line 1420 of file lock.c.

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

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

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

◆ LockHasWaiters()

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

Definition at line 634 of file lock.c.

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

Referenced by LockHasWaitersRelation().

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

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 598 of file lock.c.

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

Referenced by CheckRelationLockedByMe().

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

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2579 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ LockReassignOwner()

static void LockReassignOwner ( LOCALLOCK locallock,
ResourceOwner  parent 
)
static

Definition at line 2609 of file lock.c.

References CurrentResourceOwner, i, LOCALLOCK::lockOwners, LOCALLOCKOWNER::nLocks, LOCALLOCK::numLockOwners, LOCALLOCKOWNER::owner, ResourceOwnerForgetLock(), and ResourceOwnerRememberLock().

Referenced by LockReassignCurrentOwner().

2610 {
2611  LOCALLOCKOWNER *lockOwners;
2612  int i;
2613  int ic = -1;
2614  int ip = -1;
2615 
2616  /*
2617  * Scan to see if there are any locks belonging to current owner or its
2618  * parent
2619  */
2620  lockOwners = locallock->lockOwners;
2621  for (i = locallock->numLockOwners - 1; i >= 0; i--)
2622  {
2623  if (lockOwners[i].owner == CurrentResourceOwner)
2624  ic = i;
2625  else if (lockOwners[i].owner == parent)
2626  ip = i;
2627  }
2628 
2629  if (ic < 0)
2630  return; /* no current locks */
2631 
2632  if (ip < 0)
2633  {
2634  /* Parent has no slot, so just give it the child's slot */
2635  lockOwners[ic].owner = parent;
2636  ResourceOwnerRememberLock(parent, locallock);
2637  }
2638  else
2639  {
2640  /* Merge child's count with parent's */
2641  lockOwners[ip].nLocks += lockOwners[ic].nLocks;
2642  /* compact out unused slot */
2643  locallock->numLockOwners--;
2644  if (ic < locallock->numLockOwners)
2645  lockOwners[ic] = lockOwners[locallock->numLockOwners];
2646  }
2648 }
int numLockOwners
Definition: lock.h:415
int64 nLocks
Definition: lock.h:402
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:977
LOCALLOCKOWNER * lockOwners
Definition: lock.h:417
int i
struct ResourceOwnerData * owner
Definition: lock.h:401
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:957

◆ LockRefindAndRelease()

static void LockRefindAndRelease ( LockMethod  lockMethodTable,
PGPROC proc,
LOCKTAG locktag,
LOCKMODE  lockmode,
bool  decrement_strong_lock_count 
)
static

Definition at line 3133 of file lock.c.

References Assert, CleanUpLock(), ConflictsWithRelationFastPath, FastPathStrongRelationLockData::count, elog, FastPathStrongLockHashPartition, HASH_FIND, hash_search_with_hash_value(), PROCLOCK::holdMask, LOCKBIT_ON, LockHashPartitionLock, LockMethodData::lockModeNames, TwoPhaseLockRecord::locktag, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), FastPathStrongRelationLockData::mutex, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, PANIC, PROCLOCK_PRINT, ProcLockHashCode(), SpinLockAcquire, SpinLockRelease, UnGrantLock(), and WARNING.

Referenced by lock_twophase_postcommit(), LockReleaseAll(), and VirtualXactLockTableCleanup().

3136 {
3137  LOCK *lock;
3138  PROCLOCK *proclock;
3139  PROCLOCKTAG proclocktag;
3140  uint32 hashcode;
3141  uint32 proclock_hashcode;
3142  LWLock *partitionLock;
3143  bool wakeupNeeded;
3144 
3145  hashcode = LockTagHashCode(locktag);
3146  partitionLock = LockHashPartitionLock(hashcode);
3147 
3148  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3149 
3150  /*
3151  * Re-find the lock object (it had better be there).
3152  */
3154  (void *) locktag,
3155  hashcode,
3156  HASH_FIND,
3157  NULL);
3158  if (!lock)
3159  elog(PANIC, "failed to re-find shared lock object");
3160 
3161  /*
3162  * Re-find the proclock object (ditto).
3163  */
3164  proclocktag.myLock = lock;
3165  proclocktag.myProc = proc;
3166 
3167  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
3168 
3170  (void *) &proclocktag,
3171  proclock_hashcode,
3172  HASH_FIND,
3173  NULL);
3174  if (!proclock)
3175  elog(PANIC, "failed to re-find shared proclock object");
3176 
3177  /*
3178  * Double-check that we are actually holding a lock of the type we want to
3179  * release.
3180  */
3181  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
3182  {
3183  PROCLOCK_PRINT("lock_twophase_postcommit: WRONGTYPE", proclock);
3184  LWLockRelease(partitionLock);
3185  elog(WARNING, "you don't own a lock of type %s",
3186  lockMethodTable->lockModeNames[lockmode]);
3187  return;
3188  }
3189 
3190  /*
3191  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
3192  */
3193  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
3194 
3195  CleanUpLock(lock, proclock,
3196  lockMethodTable, hashcode,
3197  wakeupNeeded);
3198 
3199  LWLockRelease(partitionLock);
3200 
3201  /*
3202  * Decrement strong lock count. This logic is needed only for 2PC.
3203  */
3204  if (decrement_strong_lock_count
3205  && ConflictsWithRelationFastPath(locktag, lockmode))
3206  {
3207  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
3208 
3210  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
3211  FastPathStrongRelationLocks->count[fasthashcode]--;
3213  }
3214 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:940
Definition: lwlock.h:31
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:232
LOCKMASK holdMask
Definition: lock.h:355
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:268
#define LockHashPartitionLock(hashcode)
Definition: lock.h:504
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:262
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:271
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:565
unsigned int uint32
Definition: c.h:374
Definition: lock.h:287
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:517
#define WARNING
Definition: elog.h:40
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:745
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
PGPROC * myProc
Definition: lock.h:345
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:348
#define elog(elevel,...)
Definition: elog.h:214
LOCK * myLock
Definition: lock.h:344
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1578
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:365
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1635
const char *const * lockModeNames
Definition: lock.h:114

◆ LockRelease()

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

Definition at line 1975 of file lock.c.

References Assert, CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FastPathLocalUseCount, FastPathUnGrantRelationLock(), PGPROC::fpInfoLock, HASH_FIND, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PROCLOCK::holdMask, i, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, LOCALLOCK::lockCleared, LockHashPartitionLock, TwoPhaseLockRecord::lockmode, LockMethodData::lockModeNames, LOCALLOCK::lockOwners, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, LOCALLOCK::nLocks, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, LOCALLOCK::proclock, PROCLOCK_PRINT, RemoveLocalLock(), ResourceOwnerForgetLock(), UnGrantLock(), and WARNING.

Referenced by ConditionalXactLockTableWait(), pg_advisory_unlock_int4(), pg_advisory_unlock_int8(), pg_advisory_unlock_shared_int4(), pg_advisory_unlock_shared_int8(), ReleaseLockIfHeld(), SpeculativeInsertionLockRelease(), SpeculativeInsertionWait(), StandbyReleaseLockList(), UnlockDatabaseObject(), UnlockPage(), UnlockRelation(), UnlockRelationForExtension(), UnlockRelationId(), UnlockRelationIdForSession(), UnlockRelationOid(), UnlockSharedObject(), UnlockSharedObjectForSession(), UnlockTuple(), VirtualXactLock(), XactLockTableDelete(), and XactLockTableWait().

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

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2180 of file lock.c.

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

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

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

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2484 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

Definition at line 2454 of file lock.c.

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

Referenced by pg_advisory_unlock_all().

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

◆ LockShmemSize()

Size LockShmemSize ( void  )

Definition at line 3532 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 517 of file lock.c.

References get_hash_value().

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

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

Definition at line 4558 of file lock.c.

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

Referenced by RelationExtensionLockWaiterCount().

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

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

Definition at line 1799 of file lock.c.

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

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

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

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

Definition at line 3340 of file lock.c.

References Assert, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), LOCK::grantMask, PROCLOCK::groupLeader, hash_seq_init(), hash_seq_search(), hash_update_hash_key(), PROCLOCK::holdMask, i, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartitionLockByIndex, LOCALLOCK::lockOwners, LOCKTAG::locktag_type, LOCKTAG_VIRTUALTRANSACTION, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCALLOCK::nLocks, LOCK::nRequested, NUM_LOCK_PARTITIONS, LOCALLOCK::numLockOwners, offsetof, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), SHMQueueDelete(), SHMQueueInsertBefore(), SHMQueueNext(), START_CRIT_SECTION, status(), LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, and TwoPhaseGetDummyProc().

Referenced by PrepareTransaction().

3341 {
3342  PGPROC *newproc = TwoPhaseGetDummyProc(xid, false);
3344  LOCALLOCK *locallock;
3345  LOCK *lock;
3346  PROCLOCK *proclock;
3347  PROCLOCKTAG proclocktag;
3348  int partition;
3349 
3350  /* Can't prepare a lock group follower. */
3351  Assert(MyProc->lockGroupLeader == NULL ||
3353 
3354  /* This is a critical section: any error means big trouble */
3356 
3357  /*
3358  * First we run through the locallock table and get rid of unwanted
3359  * entries, then we scan the process's proclocks and transfer them to the
3360  * target proc.
3361  *
3362  * We do this separately because we may have multiple locallock entries
3363  * pointing to the same proclock, and we daren't end up with any dangling
3364  * pointers.
3365  */
3367 
3368  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3369  {
3370  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3371  bool haveSessionLock;
3372  bool haveXactLock;
3373  int i;
3374 
3375  if (locallock->proclock == NULL || locallock->lock == NULL)
3376  {
3377  /*
3378  * We must've run out of shared memory while trying to set up this
3379  * lock. Just forget the local entry.
3380  */
3381  Assert(locallock->nLocks == 0);
3382  RemoveLocalLock(locallock);
3383  continue;
3384  }
3385 
3386  /* Ignore VXID locks */
3387  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)