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:86
#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:793
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:74
#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 1756 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

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

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

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

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

◆ BeginStrongLockAcquire()

static void BeginStrongLockAcquire ( LOCALLOCK locallock,
uint32  fasthashcode 
)
static

Definition at line 1720 of file lock.c.

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

Referenced by LockAcquireExtended().

1721 {
1722  Assert(StrongLockInProgress == NULL);
1723  Assert(locallock->holdsStrongLockCount == false);
1724 
1725  /*
1726  * Adding to a memory location is not atomic, so we take a spinlock to
1727  * ensure we don't collide with someone else trying to bump the count at
1728  * the same time.
1729  *
1730  * XXX: It might be worth considering using an atomic fetch-and-add
1731  * instruction here, on architectures where that is supported.
1732  */
1733 
1735  FastPathStrongRelationLocks->count[fasthashcode]++;
1736  locallock->holdsStrongLockCount = true;
1737  StrongLockInProgress = locallock;
1739 }
bool holdsStrongLockCount
Definition: lock.h:428
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:792

◆ CheckAndSetLockHeld()

static void CheckAndSetLockHeld ( LOCALLOCK locallock,
bool  acquired 
)
inlinestatic

Definition at line 1351 of file lock.c.

References LOCALLOCK_LOCKTAG, LOCKTAG_PAGE, and LOCKTAG_RELATION_EXTEND.

Referenced by GrantLockLocal(), and RemoveLocalLock().

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

◆ CleanUpLock()

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

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

1637 {
1638  /*
1639  * If this was my last hold on this lock, delete my entry in the proclock
1640  * table.
1641  */
1642  if (proclock->holdMask == 0)
1643  {
1644  uint32 proclock_hashcode;
1645 
1646  PROCLOCK_PRINT("CleanUpLock: deleting", proclock);
1647  SHMQueueDelete(&proclock->lockLink);
1648  SHMQueueDelete(&proclock->procLink);
1649  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
1651  (void *) &(proclock->tag),
1652  proclock_hashcode,
1653  HASH_REMOVE,
1654  NULL))
1655  elog(PANIC, "proclock table corrupted");
1656  }
1657 
1658  if (lock->nRequested == 0)
1659  {
1660  /*
1661  * The caller just released the last lock, so garbage-collect the lock
1662  * object.
1663  */
1664  LOCK_PRINT("CleanUpLock: deleting", lock, 0);
1665  Assert(SHMQueueEmpty(&(lock->procLocks)));
1667  (void *) &(lock->tag),
1668  hashcode,
1669  HASH_REMOVE,
1670  NULL))
1671  elog(PANIC, "lock table corrupted");
1672  }
1673  else if (wakeupNeeded)
1674  {
1675  /* There are waiters on this lock, so wake them up. */
1676  ProcLockWakeup(lockMethodTable, lock);
1677  }
1678 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:967
PROCLOCKTAG tag
Definition: lock.h:361
int nRequested
Definition: lock.h:308
LOCKMASK holdMask
Definition: lock.h:365
LOCKTAG tag
Definition: lock.h:300
SHM_QUEUE lockLink
Definition: lock.h:367
static HTAB * LockMethodProcLockHash
Definition: lock.c:281
#define PANIC
Definition: elog.h:55
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:564
unsigned int uint32
Definition: c.h:429
SHM_QUEUE procLocks
Definition: lock.h:305
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1696
SHM_QUEUE procLink
Definition: lock.h:368
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:364
#define Assert(condition)
Definition: c.h:792
static HTAB * LockMethodLockHash
Definition: lock.c:280
#define elog(elevel,...)
Definition: elog.h:228
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 582 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

583 {
584  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
585 
586  if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
587  return true;
588 
589  return false;
590 }
const LOCKMASK * conflictTab
Definition: lock.h: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 2809 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().

2810 {
2811  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
2812  LOCKTAG *locktag = &locallock->tag.lock;
2813  PROCLOCK *proclock = NULL;
2814  LWLock *partitionLock = LockHashPartitionLock(locallock->hashcode);
2815  Oid relid = locktag->locktag_field2;
2816  uint32 f;
2817 
2819 
2820  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2821  {
2822  uint32 lockmode;
2823 
2824  /* Look for an allocated slot matching the given relid. */
2825  if (relid != MyProc->fpRelId[f] || FAST_PATH_GET_BITS(MyProc, f) == 0)
2826  continue;
2827 
2828  /* If we don't have a lock of the given mode, forget it! */
2829  lockmode = locallock->tag.mode;
2830  if (!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2831  break;
2832 
2833  /* Find or create lock object. */
2834  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2835 
2836  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
2837  locallock->hashcode, lockmode);
2838  if (!proclock)
2839  {
2840  LWLockRelease(partitionLock);
2842  ereport(ERROR,
2843  (errcode(ERRCODE_OUT_OF_MEMORY),
2844  errmsg("out of shared memory"),
2845  errhint("You might need to increase max_locks_per_transaction.")));
2846  }
2847  GrantLock(proclock->tag.myLock, proclock, lockmode);
2848  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2849 
2850  LWLockRelease(partitionLock);
2851 
2852  /* No need to examine remaining slots. */
2853  break;
2854  }
2855 
2857 
2858  /* Lock may have already been transferred by some other backend. */
2859  if (proclock == NULL)
2860  {
2861  LOCK *lock;
2862  PROCLOCKTAG proclocktag;
2863  uint32 proclock_hashcode;
2864 
2865  LWLockAcquire(partitionLock, LW_SHARED);
2866 
2868  (void *) locktag,
2869  locallock->hashcode,
2870  HASH_FIND,
2871  NULL);
2872  if (!lock)
2873  elog(ERROR, "failed to re-find shared lock object");
2874 
2875  proclocktag.myLock = lock;
2876  proclocktag.myProc = MyProc;
2877 
2878  proclock_hashcode = ProcLockHashCode(&proclocktag, locallock->hashcode);
2879  proclock = (PROCLOCK *)
2881  (void *) &proclocktag,
2882  proclock_hashcode,
2883  HASH_FIND,
2884  NULL);
2885  if (!proclock)
2886  elog(ERROR, "failed to re-find shared proclock object");
2887  LWLockRelease(partitionLock);
2888  }
2889 
2890  return proclock;
2891 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:967
PROCLOCKTAG tag
Definition: lock.h:361
uint32 hashcode
Definition: lock.h:421
Definition: lwlock.h:31
LOCALLOCKTAG tag
Definition: lock.h:418
int errhint(const char *fmt,...)
Definition: elog.c:1162
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1169
LOCKTAG lock
Definition: lock.h:399
LOCKMODE mode
Definition: lock.h:400
PGPROC * MyProc
Definition: proc.c:68
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1554
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:204
Definition: lock.h:164
#define LockHashPartitionLock(hashcode)
Definition: lock.h:514
int errcode(int sqlerrcode)
Definition: elog.c:704
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:1810
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:215
#define ERROR
Definition: elog.h:45
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:564
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:74
uint32 locktag_field2
Definition: lock.h:167
unsigned int uint32
Definition: c.h:429
Definition: lock.h:297
#define ereport(elevel,...)
Definition: elog.h:155
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:240
static HTAB * LockMethodLockHash
Definition: lock.c:280
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
PGPROC * myProc
Definition: lock.h:355
Definition: lock.h:358
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define elog(elevel,...)
Definition: elog.h:228
LOCK * myLock
Definition: lock.h:354
static const LockMethod LockMethods[]
Definition: lock.c:150
LWLock fpInfoLock
Definition: proc.h:238
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:213

◆ FastPathGrantRelationLock()

static bool FastPathGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

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

2655 {
2656  uint32 f;
2657  uint32 unused_slot = FP_LOCK_SLOTS_PER_BACKEND;
2658 
2659  /* Scan for existing entry for this relid, remembering empty slot. */
2660  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2661  {
2662  if (FAST_PATH_GET_BITS(MyProc, f) == 0)
2663  unused_slot = f;
2664  else if (MyProc->fpRelId[f] == relid)
2665  {
2666  Assert(!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode));
2667  FAST_PATH_SET_LOCKMODE(MyProc, f, lockmode);
2668  return true;
2669  }
2670  }
2671 
2672  /* If no existing entry, use any empty slot. */
2673  if (unused_slot < FP_LOCK_SLOTS_PER_BACKEND)
2674  {
2675  MyProc->fpRelId[unused_slot] = relid;
2676  FAST_PATH_SET_LOCKMODE(MyProc, unused_slot, lockmode);
2678  return true;
2679  }
2680 
2681  /* No existing entry, and no empty slot. */
2682  return false;
2683 }
PGPROC * MyProc
Definition: proc.c:68
#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:74
unsigned int uint32
Definition: c.h:429
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:240
#define Assert(condition)
Definition: c.h:792

◆ FastPathTransferRelationLocks()

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

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

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

◆ FastPathUnGrantRelationLock()

static bool FastPathUnGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

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

2692 {
2693  uint32 f;
2694  bool result = false;
2695 
2697  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2698  {
2699  if (MyProc->fpRelId[f] == relid
2700  && FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2701  {
2702  Assert(!result);
2703  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2704  result = true;
2705  /* we continue iterating so as to update FastPathLocalUseCount */
2706  }
2707  if (FAST_PATH_GET_BITS(MyProc, f) != 0)
2709  }
2710  return result;
2711 }
PGPROC * MyProc
Definition: proc.c:68
#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:74
unsigned int uint32
Definition: c.h:429
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:240
#define Assert(condition)
Definition: c.h:792
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:213

◆ FinishStrongLockAcquire()

static void FinishStrongLockAcquire ( void  )
static

Definition at line 1746 of file lock.c.

Referenced by LockAcquireExtended().

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

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

Definition at line 3752 of file lock.c.

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

Referenced by pg_blocking_pids().

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

◆ GetLockConflicts()

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

Definition at line 2911 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 ProcSleep(), ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

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

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

Definition at line 4014 of file lock.c.

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

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

4015 {
4016  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
4017  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
4018  return LockMethods[lockmethodid]->lockModeNames[mode];
4019 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define lengthof(array)
Definition: c.h:722
#define Assert(condition)
Definition: c.h:792
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 486 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

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

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

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

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

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 498 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

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

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

Definition at line 3932 of file lock.c.

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

Referenced by LogStandbySnapshot().

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

◆ GetSingleProcBlockerStatusData()

static void GetSingleProcBlockerStatusData ( PGPROC blocked_proc,
BlockedProcsData data 
)
static

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

3833 {
3834  LOCK *theLock = blocked_proc->waitLock;
3835  BlockedProcData *bproc;
3836  SHM_QUEUE *procLocks;
3837  PROCLOCK *proclock;
3838  PROC_QUEUE *waitQueue;
3839  PGPROC *proc;
3840  int queue_size;
3841  int i;
3842 
3843  /* Nothing to do if this proc is not blocked */
3844  if (theLock == NULL)
3845  return;
3846 
3847  /* Set up a procs[] element */
3848  bproc = &data->procs[data->nprocs++];
3849  bproc->pid = blocked_proc->pid;
3850  bproc->first_lock = data->nlocks;
3851  bproc->first_waiter = data->npids;
3852 
3853  /*
3854  * We may ignore the proc's fast-path arrays, since nothing in those could
3855  * be related to a contended lock.
3856  */
3857 
3858  /* Collect all PROCLOCKs associated with theLock */
3859  procLocks = &(theLock->procLocks);
3860  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3861  offsetof(PROCLOCK, lockLink));
3862  while (proclock)
3863  {
3864  PGPROC *proc = proclock->tag.myProc;
3865  LOCK *lock = proclock->tag.myLock;
3866  LockInstanceData *instance;
3867 
3868  if (data->nlocks >= data->maxlocks)
3869  {
3870  data->maxlocks += MaxBackends;
3871  data->locks = (LockInstanceData *)
3872  repalloc(data->locks, sizeof(LockInstanceData) * data->maxlocks);
3873  }
3874 
3875  instance = &data->locks[data->nlocks];
3876  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3877  instance->holdMask = proclock->holdMask;
3878  if (proc->waitLock == lock)
3879  instance->waitLockMode = proc->waitLockMode;
3880  else
3881  instance->waitLockMode = NoLock;
3882  instance->backend = proc->backendId;
3883  instance->lxid = proc->lxid;
3884  instance->pid = proc->pid;
3885  instance->leaderPid = proclock->groupLeader->pid;
3886  instance->fastpath = false;
3887  data->nlocks++;
3888 
3889  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3890  offsetof(PROCLOCK, lockLink));
3891  }
3892 
3893  /* Enlarge waiter_pids[] if it's too small to hold all wait queue PIDs */
3894  waitQueue = &(theLock->waitProcs);
3895  queue_size = waitQueue->size;
3896 
3897  if (queue_size > data->maxpids - data->npids)
3898  {
3899  data->maxpids = Max(data->maxpids + MaxBackends,
3900  data->npids + queue_size);
3901  data->waiter_pids = (int *) repalloc(data->waiter_pids,
3902  sizeof(int) * data->maxpids);
3903  }
3904 
3905  /* Collect PIDs from the lock's wait queue, stopping at blocked_proc */
3906  proc = (PGPROC *) waitQueue->links.next;
3907  for (i = 0; i < queue_size; i++)
3908  {
3909  if (proc == blocked_proc)
3910  break;
3911  data->waiter_pids[data->npids++] = proc->pid;
3912  proc = (PGPROC *) proc->links.next;
3913  }
3914 
3915  bproc->num_locks = data->nlocks - bproc->first_lock;
3916  bproc->num_waiters = data->npids - bproc->first_waiter;
3917 }
PROCLOCKTAG tag
Definition: lock.h:361
int * waiter_pids
Definition: lock.h:476
BackendId backendId
Definition: proc.h:153
int first_lock
Definition: lock.h:464
SHM_QUEUE links
Definition: lock.h:31
int num_waiters
Definition: lock.h:469
LOCKMASK holdMask
Definition: lock.h:365
SHM_QUEUE links
Definition: proc.h:124
struct SHM_QUEUE * next
Definition: shmem.h:31
bool fastpath
Definition: lock.h:450
LOCKMODE waitLockMode
Definition: proc.h:181
LOCKTAG tag
Definition: lock.h:300
Definition: lock.h:164
SHM_QUEUE lockLink
Definition: lock.h:367
BlockedProcData * procs
Definition: lock.h:474
LOCKTAG locktag
Definition: lock.h:443
LOCKMODE waitLockMode
Definition: lock.h:445
int num_locks
Definition: lock.h:465
PROC_QUEUE waitProcs
Definition: lock.h:306
int leaderPid
Definition: lock.h:449
int MaxBackends
Definition: globals.c:137
#define NoLock
Definition: lockdefs.h:34
Definition: lock.h:297
LOCK * waitLock
Definition: proc.h:179
int maxlocks
Definition: lock.h:480
SHM_QUEUE procLocks
Definition: lock.h:305
LockInstanceData * locks
Definition: lock.h:475
BackendId backend
Definition: lock.h:446
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
int first_waiter
Definition: lock.h:468
#define Max(x, y)
Definition: c.h:968
LocalTransactionId lxid
Definition: lock.h:447
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
LOCKMASK holdMask
Definition: lock.h:444
PGPROC * myProc
Definition: lock.h:355
Definition: lock.h:358
int i
int size
Definition: lock.h:32
LOCK * myLock
Definition: lock.h:354
Definition: proc.h:121
int pid
Definition: proc.h:146
#define offsetof(type, field)
Definition: c.h:715
PGPROC * groupLeader
Definition: lock.h:364
LocalTransactionId lxid
Definition: proc.h:143

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1785 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

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

◆ GrantLock()

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

Definition at line 1554 of file lock.c.

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

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

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

◆ GrantLockLocal()

static void GrantLockLocal ( LOCALLOCK locallock,
ResourceOwner  owner 
)
static

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

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

◆ InitLocks()

void InitLocks ( void  )

Definition at line 404 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ lock_twophase_postabort()

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

Definition at line 4366 of file lock.c.

References lock_twophase_postcommit().

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

◆ lock_twophase_postcommit()

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

Definition at line 4340 of file lock.c.

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

Referenced by lock_twophase_postabort().

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

◆ lock_twophase_recover()

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

Definition at line 4127 of file lock.c.

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

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

◆ lock_twophase_standby_recover()

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

Definition at line 4308 of file lock.c.

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

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

◆ LockAcquire()

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

◆ LockAcquireExtended()

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

Definition at line 770 of file lock.c.

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

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

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

◆ LockCheckConflicts()

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

Definition at line 1419 of file lock.c.

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

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

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

◆ LockHasWaiters()

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

Definition at line 633 of file lock.c.

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

Referenced by LockHasWaitersRelation().

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

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 597 of file lock.c.

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

Referenced by CheckRelationLockedByMe().

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

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2578 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ LockReassignOwner()

static void LockReassignOwner ( LOCALLOCK locallock,
ResourceOwner  parent 
)
static

Definition at line 2608 of file lock.c.

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

Referenced by LockReassignCurrentOwner().

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

◆ LockRefindAndRelease()

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

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

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

◆ LockRelease()

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

Definition at line 1974 of file lock.c.

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

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

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

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2179 of file lock.c.

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

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

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

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2483 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

Definition at line 2453 of file lock.c.

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

Referenced by pg_advisory_unlock_all().

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

◆ LockShmemSize()

Size LockShmemSize ( void  )

Definition at line 3531 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 516 of file lock.c.

References get_hash_value().

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

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

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

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

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

Definition at line 1798 of file lock.c.

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

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

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

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

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

3340 {
3341  PGPROC *newproc = TwoPhaseGetDummyProc(xid, false);
3343  LOCALLOCK *locallock;
3344  LOCK *lock;
3345  PROCLOCK *proclock;
3346  PROCLOCKTAG proclocktag;
3347  int partition;
3348 
3349  /* Can't prepare a lock group follower. */
3350  Assert(MyProc->lockGroupLeader == NULL ||
3352 
3353  /* This is a critical section: any error means big trouble */
3355 
3356  /*
3357  * First we run through the locallock table and get rid of unwanted
3358  * entries, then we scan the process's proclocks and transfer them to the
3359  * target proc.
3360  *
3361  * We do this separately because we may have multiple locallock entries
3362  * pointing to the same proclock, and we daren't end up with any dangling
3363  * pointers.
3364  */
3366 
3367  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3368  {
3369  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3370  bool haveSessionLock;
3371  bool haveXactLock;
3372  int i;
3373 
3374  if (locallock->proclock == NULL || locallock->lock == NULL)
3375  {
3376  /*
3377  * We must've run out of shared memory while trying to set up this
3378  * lock. Just forget the local entry.
3379  */
3380  Assert(locallock->nLocks == 0);
3381  RemoveLocalLock(locallock);
3382  continue;
3383  }
3384 
3385  /* Ignore VXID locks */
3386  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3387  continue;
3388 
3389  /* Scan to see whether we hold it at session or transaction level */
3390  haveSessionLock = haveXactLock = false;
3391  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3392  {
3393  if (lockOwners[i].owner == NULL)
3394  haveSessionLock = true;
3395  else
3396  haveXactLock = true;
3397  }
3398 
3399  /* Ignore it if we have only session lock */
3400  if (!haveXactLock)
3401  continue;
3402 
3403  /* This can't happen, because we already checked it */
3404  if (haveSessionLock)