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)
 
int 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 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 205 of file lock.c.

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

◆ EligibleForRelationFastPath

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

Definition at line 199 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:740
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
#define FAST_PATH_BITS_PER_SLOT
Definition: lock.c:174

Definition at line 179 of file lock.c.

◆ FAST_PATH_BITS_PER_SLOT

#define FAST_PATH_BITS_PER_SLOT   3

Definition at line 174 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 175 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 176 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 184 of file lock.c.

Referenced by FastPathGrantRelationLock().

◆ FAST_PATH_STRONG_LOCK_HASH_BITS

#define FAST_PATH_STRONG_LOCK_HASH_BITS   10

Definition at line 232 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 233 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 1666 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

1667 {
1668  uint32 fasthashcode;
1669  LOCALLOCK *locallock = StrongLockInProgress;
1670 
1671  if (locallock == NULL)
1672  return;
1673 
1674  fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
1675  Assert(locallock->holdsStrongLockCount == true);
1677  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1678  FastPathStrongRelationLocks->count[fasthashcode]--;
1679  locallock->holdsStrongLockCount = false;
1680  StrongLockInProgress = NULL;
1682 }
uint32 hashcode
Definition: lock.h:410
bool holdsStrongLockCount
Definition: lock.h:417
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:259
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
unsigned int uint32
Definition: c.h:359
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:739

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )

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

3140 {
3142  LOCALLOCK *locallock;
3143 
3144  /*
3145  * For the most part, we don't need to touch shared memory for this ---
3146  * all the necessary state information is in the locallock table.
3147  * Fast-path locks are an exception, however: we move any such locks to
3148  * the main table before allowing PREPARE TRANSACTION to succeed.
3149  */
3151 
3152  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3153  {
3154  TwoPhaseLockRecord record;
3155  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3156  bool haveSessionLock;
3157  bool haveXactLock;
3158  int i;
3159 
3160  /*
3161  * Ignore VXID locks. We don't want those to be held by prepared
3162  * transactions, since they aren't meaningful after a restart.
3163  */
3164  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3165  continue;
3166 
3167  /* Ignore it if we don't actually hold the lock */
3168  if (locallock->nLocks <= 0)
3169  continue;
3170 
3171  /* Scan to see whether we hold it at session or transaction level */
3172  haveSessionLock = haveXactLock = false;
3173  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3174  {
3175  if (lockOwners[i].owner == NULL)
3176  haveSessionLock = true;
3177  else
3178  haveXactLock = true;
3179  }
3180 
3181  /* Ignore it if we have only session lock */
3182  if (!haveXactLock)
3183  continue;
3184 
3185  /*
3186  * If we have both session- and transaction-level locks, fail. This
3187  * should never happen with regular locks, since we only take those at
3188  * session level in some special operations like VACUUM. It's
3189  * possible to hit this with advisory locks, though.
3190  *
3191  * It would be nice if we could keep the session hold and give away
3192  * the transactional hold to the prepared xact. However, that would
3193  * require two PROCLOCK objects, and we cannot be sure that another
3194  * PROCLOCK will be available when it comes time for PostPrepare_Locks
3195  * to do the deed. So for now, we error out while we can still do so
3196  * safely.
3197  */
3198  if (haveSessionLock)
3199  ereport(ERROR,
3200  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3201  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3202 
3203  /*
3204  * If the local lock was taken via the fast-path, we need to move it
3205  * to the primary lock table, or just get a pointer to the existing
3206  * primary lock table entry if by chance it's already been
3207  * transferred.
3208  */
3209  if (locallock->proclock == NULL)
3210  {
3211  locallock->proclock = FastPathGetRelationLockEntry(locallock);
3212  locallock->lock = locallock->proclock->tag.myLock;
3213  }
3214 
3215  /*
3216  * Arrange to not release any strong lock count held by this lock
3217  * entry. We must retain the count until the prepared transaction is
3218  * committed or rolled back.
3219  */
3220  locallock->holdsStrongLockCount = false;
3221 
3222  /*
3223  * Create a 2PC record.
3224  */
3225  memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3226  record.lockmode = locallock->tag.mode;
3227 
3229  &record, sizeof(TwoPhaseLockRecord));
3230  }
3231 }
PROCLOCKTAG tag
Definition: lock.h:350
LOCALLOCKTAG tag
Definition: lock.h:407
static HTAB * LockMethodLocalHash
Definition: lock.c:255
bool holdsStrongLockCount
Definition: lock.h:417
int numLockOwners
Definition: lock.h:414
LOCKTAG lock
Definition: lock.h:388
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition: lock.c:2719
LOCKMODE mode
Definition: lock.h:389
PROCLOCK * proclock
Definition: lock.h:412
Definition: lock.h:163
int errcode(int sqlerrcode)
Definition: elog.c:608
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition: twophase.c:1187
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
uint8 locktag_type
Definition: lock.h:169
#define TWOPHASE_RM_LOCK_ID
Definition: twophase_rmgr.h:25
LOCALLOCKOWNER * lockOwners
Definition: lock.h:416
LOCK * lock
Definition: lock.h:411
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int64 nLocks
Definition: lock.h:413
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
LOCK * myLock
Definition: lock.h:343
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
LOCKMODE lockmode
Definition: lock.c:161

◆ BeginStrongLockAcquire()

static void BeginStrongLockAcquire ( LOCALLOCK locallock,
uint32  fasthashcode 
)
static

Definition at line 1630 of file lock.c.

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

Referenced by LockAcquireExtended().

1631 {
1632  Assert(StrongLockInProgress == NULL);
1633  Assert(locallock->holdsStrongLockCount == false);
1634 
1635  /*
1636  * Adding to a memory location is not atomic, so we take a spinlock to
1637  * ensure we don't collide with someone else trying to bump the count at
1638  * the same time.
1639  *
1640  * XXX: It might be worth considering using an atomic fetch-and-add
1641  * instruction here, on architectures where that is supported.
1642  */
1643 
1645  FastPathStrongRelationLocks->count[fasthashcode]++;
1646  locallock->holdsStrongLockCount = true;
1647  StrongLockInProgress = locallock;
1649 }
bool holdsStrongLockCount
Definition: lock.h:417
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:259
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:739

◆ CleanUpLock()

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

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

1550 {
1551  /*
1552  * If this was my last hold on this lock, delete my entry in the proclock
1553  * table.
1554  */
1555  if (proclock->holdMask == 0)
1556  {
1557  uint32 proclock_hashcode;
1558 
1559  PROCLOCK_PRINT("CleanUpLock: deleting", proclock);
1560  SHMQueueDelete(&proclock->lockLink);
1561  SHMQueueDelete(&proclock->procLink);
1562  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
1564  (void *) &(proclock->tag),
1565  proclock_hashcode,
1566  HASH_REMOVE,
1567  NULL))
1568  elog(PANIC, "proclock table corrupted");
1569  }
1570 
1571  if (lock->nRequested == 0)
1572  {
1573  /*
1574  * The caller just released the last lock, so garbage-collect the lock
1575  * object.
1576  */
1577  LOCK_PRINT("CleanUpLock: deleting", lock, 0);
1578  Assert(SHMQueueEmpty(&(lock->procLocks)));
1580  (void *) &(lock->tag),
1581  hashcode,
1582  HASH_REMOVE,
1583  NULL))
1584  elog(PANIC, "lock table corrupted");
1585  }
1586  else if (wakeupNeeded)
1587  {
1588  /* There are waiters on this lock, so wake them up. */
1589  ProcLockWakeup(lockMethodTable, lock);
1590  }
1591 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
PROCLOCKTAG tag
Definition: lock.h:350
int nRequested
Definition: lock.h:298
LOCKMASK holdMask
Definition: lock.h:354
LOCKTAG tag
Definition: lock.h:290
SHM_QUEUE lockLink
Definition: lock.h:356
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define PANIC
Definition: elog.h:53
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
unsigned int uint32
Definition: c.h:359
SHM_QUEUE procLocks
Definition: lock.h:295
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1628
SHM_QUEUE procLink
Definition: lock.h:357
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:739
static HTAB * LockMethodLockHash
Definition: lock.c:253
#define elog(elevel,...)
Definition: elog.h:228
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 556 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

557 {
558  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
559 
560  if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
561  return true;
562 
563  return false;
564 }
const LOCKMASK * conflictTab
Definition: lock.h: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 2719 of file lock.c.

References PGPROC::backendLock, 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::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().

2720 {
2721  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
2722  LOCKTAG *locktag = &locallock->tag.lock;
2723  PROCLOCK *proclock = NULL;
2724  LWLock *partitionLock = LockHashPartitionLock(locallock->hashcode);
2725  Oid relid = locktag->locktag_field2;
2726  uint32 f;
2727 
2729 
2730  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2731  {
2732  uint32 lockmode;
2733 
2734  /* Look for an allocated slot matching the given relid. */
2735  if (relid != MyProc->fpRelId[f] || FAST_PATH_GET_BITS(MyProc, f) == 0)
2736  continue;
2737 
2738  /* If we don't have a lock of the given mode, forget it! */
2739  lockmode = locallock->tag.mode;
2740  if (!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2741  break;
2742 
2743  /* Find or create lock object. */
2744  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2745 
2746  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
2747  locallock->hashcode, lockmode);
2748  if (!proclock)
2749  {
2750  LWLockRelease(partitionLock);
2752  ereport(ERROR,
2753  (errcode(ERRCODE_OUT_OF_MEMORY),
2754  errmsg("out of shared memory"),
2755  errhint("You might need to increase max_locks_per_transaction.")));
2756  }
2757  GrantLock(proclock->tag.myLock, proclock, lockmode);
2758  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2759 
2760  LWLockRelease(partitionLock);
2761 
2762  /* No need to examine remaining slots. */
2763  break;
2764  }
2765 
2767 
2768  /* Lock may have already been transferred by some other backend. */
2769  if (proclock == NULL)
2770  {
2771  LOCK *lock;
2772  PROCLOCKTAG proclocktag;
2773  uint32 proclock_hashcode;
2774 
2775  LWLockAcquire(partitionLock, LW_SHARED);
2776 
2778  (void *) locktag,
2779  locallock->hashcode,
2780  HASH_FIND,
2781  NULL);
2782  if (!lock)
2783  elog(ERROR, "failed to re-find shared lock object");
2784 
2785  proclocktag.myLock = lock;
2786  proclocktag.myProc = MyProc;
2787 
2788  proclock_hashcode = ProcLockHashCode(&proclocktag, locallock->hashcode);
2789  proclock = (PROCLOCK *)
2791  (void *) &proclocktag,
2792  proclock_hashcode,
2793  HASH_FIND,
2794  NULL);
2795  if (!proclock)
2796  elog(ERROR, "failed to re-find shared proclock object");
2797  LWLockRelease(partitionLock);
2798  }
2799 
2800  return proclock;
2801 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
PROCLOCKTAG tag
Definition: lock.h:350
uint32 hashcode
Definition: lock.h:410
Definition: lwlock.h:32
LOCALLOCKTAG tag
Definition: lock.h:407
int errhint(const char *fmt,...)
Definition: elog.c:1069
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1119
LOCKTAG lock
Definition: lock.h:388
LOCKMODE mode
Definition: lock.h:389
PGPROC * MyProc
Definition: proc.c:67
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1467
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
Definition: lock.h:163
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
int errcode(int sqlerrcode)
Definition: elog.c:608
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
unsigned int Oid
Definition: postgres_ext.h:31
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:188
#define ERROR
Definition: elog.h:43
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
uint32 locktag_field2
Definition: lock.h:166
unsigned int uint32
Definition: c.h:359
Definition: lock.h:287
#define ereport(elevel, rest)
Definition: elog.h:141
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
LWLock backendLock
Definition: proc.h:190
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
PGPROC * myProc
Definition: lock.h:344
Definition: lock.h:347
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
LOCK * myLock
Definition: lock.h:343
static const LockMethod LockMethods[]
Definition: lock.c:150
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:186

◆ FastPathGrantRelationLock()

static bool FastPathGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

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

2565 {
2566  uint32 f;
2567  uint32 unused_slot = FP_LOCK_SLOTS_PER_BACKEND;
2568 
2569  /* Scan for existing entry for this relid, remembering empty slot. */
2570  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2571  {
2572  if (FAST_PATH_GET_BITS(MyProc, f) == 0)
2573  unused_slot = f;
2574  else if (MyProc->fpRelId[f] == relid)
2575  {
2576  Assert(!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode));
2577  FAST_PATH_SET_LOCKMODE(MyProc, f, lockmode);
2578  return true;
2579  }
2580  }
2581 
2582  /* If no existing entry, use any empty slot. */
2583  if (unused_slot < FP_LOCK_SLOTS_PER_BACKEND)
2584  {
2585  MyProc->fpRelId[unused_slot] = relid;
2586  FAST_PATH_SET_LOCKMODE(MyProc, unused_slot, lockmode);
2588  return true;
2589  }
2590 
2591  /* No existing entry, and no empty slot. */
2592  return false;
2593 }
PGPROC * MyProc
Definition: proc.c:67
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
static int FastPathLocalUseCount
Definition: lock.c:171
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:188
#define FAST_PATH_SET_LOCKMODE(proc, n, l)
Definition: lock.c:184
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
unsigned int uint32
Definition: c.h:359
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
#define Assert(condition)
Definition: c.h:739

◆ FastPathTransferRelationLocks()

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

Definition at line 2631 of file lock.c.

References PROC_HDR::allProcCount, PROC_HDR::allProcs, PGPROC::backendLock, 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::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().

2633 {
2634  LWLock *partitionLock = LockHashPartitionLock(hashcode);
2635  Oid relid = locktag->locktag_field2;
2636  uint32 i;
2637 
2638  /*
2639  * Every PGPROC that can potentially hold a fast-path lock is present in
2640  * ProcGlobal->allProcs. Prepared transactions are not, but any
2641  * outstanding fast-path locks held by prepared transactions are
2642  * transferred to the main lock table.
2643  */
2644  for (i = 0; i < ProcGlobal->allProcCount; i++)
2645  {
2646  PGPROC *proc = &ProcGlobal->allProcs[i];
2647  uint32 f;
2648 
2650 
2651  /*
2652  * If the target backend isn't referencing the same database as the
2653  * lock, then we needn't examine the individual relation IDs at all;
2654  * none of them can be relevant.
2655  *
2656  * proc->databaseId is set at backend startup time and never changes
2657  * thereafter, so it might be safe to perform this test before
2658  * acquiring &proc->backendLock. In particular, it's certainly safe
2659  * to assume that if the target backend holds any fast-path locks, it
2660  * must have performed a memory-fencing operation (in particular, an
2661  * LWLock acquisition) since setting proc->databaseId. However, it's
2662  * less clear that our backend is certain to have performed a memory
2663  * fencing operation since the other backend set proc->databaseId. So
2664  * for now, we test it after acquiring the LWLock just to be safe.
2665  */
2666  if (proc->databaseId != locktag->locktag_field1)
2667  {
2668  LWLockRelease(&proc->backendLock);
2669  continue;
2670  }
2671 
2672  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2673  {
2674  uint32 lockmode;
2675 
2676  /* Look for an allocated slot matching the given relid. */
2677  if (relid != proc->fpRelId[f] || FAST_PATH_GET_BITS(proc, f) == 0)
2678  continue;
2679 
2680  /* Find or create lock object. */
2681  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2682  for (lockmode = FAST_PATH_LOCKNUMBER_OFFSET;
2684  ++lockmode)
2685  {
2686  PROCLOCK *proclock;
2687 
2688  if (!FAST_PATH_CHECK_LOCKMODE(proc, f, lockmode))
2689  continue;
2690  proclock = SetupLockInTable(lockMethodTable, proc, locktag,
2691  hashcode, lockmode);
2692  if (!proclock)
2693  {
2694  LWLockRelease(partitionLock);
2695  LWLockRelease(&proc->backendLock);
2696  return false;
2697  }
2698  GrantLock(proclock->tag.myLock, proclock, lockmode);
2699  FAST_PATH_CLEAR_LOCKMODE(proc, f, lockmode);
2700  }
2701  LWLockRelease(partitionLock);
2702 
2703  /* No need to examine remaining slots. */
2704  break;
2705  }
2706  LWLockRelease(&proc->backendLock);
2707  }
2708  return true;
2709 }
PROCLOCKTAG tag
Definition: lock.h:350
Definition: lwlock.h:32
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1119
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1467
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
PROC_HDR * ProcGlobal
Definition: proc.c:80
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:188
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
uint32 locktag_field2
Definition: lock.h:166
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:359
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
LWLock backendLock
Definition: proc.h:190
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
uint32 allProcCount
Definition: proc.h:251
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
Definition: lock.h:347
int i
LOCK * myLock
Definition: lock.h:343
PGPROC * allProcs
Definition: proc.h:247
#define FAST_PATH_BITS_PER_SLOT
Definition: lock.c:174
uint32 locktag_field1
Definition: lock.h:165
Definition: proc.h:95
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:186

◆ FastPathUnGrantRelationLock()

static bool FastPathUnGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

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

2602 {
2603  uint32 f;
2604  bool result = false;
2605 
2607  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2608  {
2609  if (MyProc->fpRelId[f] == relid
2610  && FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2611  {
2612  Assert(!result);
2613  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2614  result = true;
2615  /* we continue iterating so as to update FastPathLocalUseCount */
2616  }
2617  if (FAST_PATH_GET_BITS(MyProc, f) != 0)
2619  }
2620  return result;
2621 }
PGPROC * MyProc
Definition: proc.c:67
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
static int FastPathLocalUseCount
Definition: lock.c:171
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:188
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
unsigned int uint32
Definition: c.h:359
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
#define Assert(condition)
Definition: c.h:739
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:186

◆ FinishStrongLockAcquire()

static void FinishStrongLockAcquire ( void  )
static

Definition at line 1656 of file lock.c.

Referenced by LockAcquireExtended().

1657 {
1658  StrongLockInProgress = NULL;
1659 }
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:259

◆ GetBlockerStatusData()

BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

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

3663 {
3664  BlockedProcsData *data;
3665  PGPROC *proc;
3666  int i;
3667 
3668  data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
3669 
3670  /*
3671  * Guess how much space we'll need, and preallocate. Most of the time
3672  * this will avoid needing to do repalloc while holding the LWLocks. (We
3673  * assume, but check with an Assert, that MaxBackends is enough entries
3674  * for the procs[] array; the other two could need enlargement, though.)
3675  */
3676  data->nprocs = data->nlocks = data->npids = 0;
3677  data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3678  data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
3679  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3680  data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3681 
3682  /*
3683  * In order to search the ProcArray for blocked_pid and assume that that
3684  * entry won't immediately disappear under us, we must hold ProcArrayLock.
3685  * In addition, to examine the lock grouping fields of any other backend,
3686  * we must hold all the hash partition locks. (Only one of those locks is
3687  * actually relevant for any one lock group, but we can't know which one
3688  * ahead of time.) It's fairly annoying to hold all those locks
3689  * throughout this, but it's no worse than GetLockStatusData(), and it
3690  * does have the advantage that we're guaranteed to return a
3691  * self-consistent instantaneous state.
3692  */
3693  LWLockAcquire(ProcArrayLock, LW_SHARED);
3694 
3695  proc = BackendPidGetProcWithLock(blocked_pid);
3696 
3697  /* Nothing to do if it's gone */
3698  if (proc != NULL)
3699  {
3700  /*
3701  * Acquire lock on the entire shared lock data structure. See notes
3702  * in GetLockStatusData().
3703  */
3704  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3706 
3707  if (proc->lockGroupLeader == NULL)
3708  {
3709  /* Easy case, proc is not a lock group member */
3710  GetSingleProcBlockerStatusData(proc, data);
3711  }
3712  else
3713  {
3714  /* Examine all procs in proc's lock group */
3715  dlist_iter iter;
3716 
3718  {
3719  PGPROC *memberProc;
3720 
3721  memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
3722  GetSingleProcBlockerStatusData(memberProc, data);
3723  }
3724  }
3725 
3726  /*
3727  * And release locks. See notes in GetLockStatusData().
3728  */
3729  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3731 
3732  Assert(data->nprocs <= data->maxprocs);
3733  }
3734 
3735  LWLockRelease(ProcArrayLock);
3736 
3737  return data;
3738 }
int * waiter_pids
Definition: lock.h:464
dlist_head lockGroupMembers
Definition: proc.h:204
#define dlist_foreach(iter, lhead)
Definition: ilist.h:507
BlockedProcData * procs
Definition: lock.h:462
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:2388
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition: lock.c:3742
#define dlist_container(type, membername, ptr)
Definition: ilist.h:477
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:505
int MaxBackends
Definition: globals.c:135
int maxlocks
Definition: lock.h:468
LockInstanceData * locks
Definition: lock.h:463
dlist_node * cur
Definition: ilist.h:161
#define Assert(condition)
Definition: c.h:739
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * palloc(Size size)
Definition: mcxt.c:949
int i
Definition: proc.h:95
PGPROC * lockGroupLeader
Definition: proc.h:203
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
int maxprocs
Definition: lock.h:466

◆ GetLockConflicts()

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

Definition at line 2821 of file lock.c.

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

Referenced by ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

2822 {
2823  static VirtualTransactionId *vxids;
2824  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
2825  LockMethod lockMethodTable;
2826  LOCK *lock;
2827  LOCKMASK conflictMask;
2828  SHM_QUEUE *procLocks;
2829  PROCLOCK *proclock;
2830  uint32 hashcode;
2831  LWLock *partitionLock;
2832  int count = 0;
2833  int fast_count = 0;
2834 
2835  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2836  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2837  lockMethodTable = LockMethods[lockmethodid];
2838  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
2839  elog(ERROR, "unrecognized lock mode: %d", lockmode);
2840 
2841  /*
2842  * Allocate memory to store results, and fill with InvalidVXID. We only
2843  * need enough space for MaxBackends + a terminator, since prepared xacts
2844  * don't count. InHotStandby allocate once in TopMemoryContext.
2845  */
2846  if (InHotStandby)
2847  {
2848  if (vxids == NULL)
2849  vxids = (VirtualTransactionId *)
2851  sizeof(VirtualTransactionId) * (MaxBackends + 1));
2852  }
2853  else
2854  vxids = (VirtualTransactionId *)
2855  palloc0(sizeof(VirtualTransactionId) * (MaxBackends + 1));
2856 
2857  /* Compute hash code and partition lock, and look up conflicting modes. */
2858  hashcode = LockTagHashCode(locktag);
2859  partitionLock = LockHashPartitionLock(hashcode);
2860  conflictMask = lockMethodTable->conflictTab[lockmode];
2861 
2862  /*
2863  * Fast path locks might not have been entered in the primary lock table.
2864  * If the lock we're dealing with could conflict with such a lock, we must
2865  * examine each backend's fast-path array for conflicts.
2866  */
2867  if (ConflictsWithRelationFastPath(locktag, lockmode))
2868  {
2869  int i;
2870  Oid relid = locktag->locktag_field2;
2871  VirtualTransactionId vxid;
2872 
2873  /*
2874  * Iterate over relevant PGPROCs. Anything held by a prepared
2875  * transaction will have been transferred to the primary lock table,
2876  * so we need not worry about those. This is all a bit fuzzy, because
2877  * new locks could be taken after we've visited a particular
2878  * partition, but the callers had better be prepared to deal with that
2879  * anyway, since the locks could equally well be taken between the
2880  * time we return the value and the time the caller does something
2881  * with it.
2882  */
2883  for (i = 0; i < ProcGlobal->allProcCount; i++)
2884  {
2885  PGPROC *proc = &ProcGlobal->allProcs[i];
2886  uint32 f;
2887 
2888  /* A backend never blocks itself */
2889  if (proc == MyProc)
2890  continue;
2891 
2893 
2894  /*
2895  * If the target backend isn't referencing the same database as
2896  * the lock, then we needn't examine the individual relation IDs
2897  * at all; none of them can be relevant.
2898  *
2899  * See FastPathTransferRelationLocks() for discussion of why we do
2900  * this test after acquiring the lock.
2901  */
2902  if (proc->databaseId != locktag->locktag_field1)
2903  {
2904  LWLockRelease(&proc->backendLock);
2905  continue;
2906  }
2907 
2908  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2909  {
2910  uint32 lockmask;
2911 
2912  /* Look for an allocated slot matching the given relid. */
2913  if (relid != proc->fpRelId[f])
2914  continue;
2915  lockmask = FAST_PATH_GET_BITS(proc, f);
2916  if (!lockmask)
2917  continue;
2918  lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
2919 
2920  /*
2921  * There can only be one entry per relation, so if we found it
2922  * and it doesn't conflict, we can skip the rest of the slots.
2923  */
2924  if ((lockmask & conflictMask) == 0)
2925  break;
2926 
2927  /* Conflict! */
2928  GET_VXID_FROM_PGPROC(vxid, *proc);
2929 
2930  /*
2931  * If we see an invalid VXID, then either the xact has already
2932  * committed (or aborted), or it's a prepared xact. In either
2933  * case we may ignore it.
2934  */
2935  if (VirtualTransactionIdIsValid(vxid))
2936  vxids[count++] = vxid;
2937 
2938  /* No need to examine remaining slots. */
2939  break;
2940  }
2941 
2942  LWLockRelease(&proc->backendLock);
2943  }
2944  }
2945 
2946  /* Remember how many fast-path conflicts we found. */
2947  fast_count = count;
2948 
2949  /*
2950  * Look up the lock object matching the tag.
2951  */
2952  LWLockAcquire(partitionLock, LW_SHARED);
2953 
2955  (const void *) locktag,
2956  hashcode,
2957  HASH_FIND,
2958  NULL);
2959  if (!lock)
2960  {
2961  /*
2962  * If the lock object doesn't exist, there is nothing holding a lock
2963  * on this lockable object.
2964  */
2965  LWLockRelease(partitionLock);
2966  vxids[count].backendId = InvalidBackendId;
2968  if (countp)
2969  *countp = count;
2970  return vxids;
2971  }
2972 
2973  /*
2974  * Examine each existing holder (or awaiter) of the lock.
2975  */
2976 
2977  procLocks = &(lock->procLocks);
2978 
2979  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2980  offsetof(PROCLOCK, lockLink));
2981 
2982  while (proclock)
2983  {
2984  if (conflictMask & proclock->holdMask)
2985  {
2986  PGPROC *proc = proclock->tag.myProc;
2987 
2988  /* A backend never blocks itself */
2989  if (proc != MyProc)
2990  {
2991  VirtualTransactionId vxid;
2992 
2993  GET_VXID_FROM_PGPROC(vxid, *proc);
2994 
2995  /*
2996  * If we see an invalid VXID, then either the xact has already
2997  * committed (or aborted), or it's a prepared xact. In either
2998  * case we may ignore it.
2999  */
3000  if (VirtualTransactionIdIsValid(vxid))
3001  {
3002  int i;
3003 
3004  /* Avoid duplicate entries. */
3005  for (i = 0; i < fast_count; ++i)
3006  if (VirtualTransactionIdEquals(vxids[i], vxid))
3007  break;
3008  if (i >= fast_count)
3009  vxids[count++] = vxid;
3010  }
3011  }
3012  }
3013 
3014  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3015  offsetof(PROCLOCK, lockLink));
3016  }
3017 
3018  LWLockRelease(partitionLock);
3019 
3020  if (count > MaxBackends) /* should never happen */
3021  elog(PANIC, "too many conflicting locks found");
3022 
3023  vxids[count].backendId = InvalidBackendId;
3025  if (countp)
3026  *countp = count;
3027  return vxids;
3028 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
PROCLOCKTAG tag
Definition: lock.h:350
Definition: lwlock.h:32
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:354
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
const LOCKMASK * conflictTab
Definition: lock.h:113
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
SHM_QUEUE lockLink
Definition: lock.h:356
#define InHotStandby
Definition: xlog.h:74
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define lengthof(array)
Definition: c.h:669
unsigned int Oid
Definition: postgres_ext.h:31
LocalTransactionId localTransactionId
Definition: lock.h:65
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
#define ERROR
Definition: elog.h:43
int MaxBackends
Definition: globals.c:135
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
uint32 locktag_field2
Definition: lock.h:166
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:359
Definition: lock.h:287
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
MemoryContext TopMemoryContext
Definition: mcxt.c:44
uint16 LOCKMETHODID
Definition: lock.h:124
SHM_QUEUE procLocks
Definition: lock.h:295
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:980
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
BackendId backendId
Definition: lock.h:64
LWLock backendLock
Definition: proc.h:190
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
uint32 allProcCount
Definition: proc.h:251
int LOCKMASK
Definition: lockdefs.h:25
uint8 locktag_lockmethodid
Definition: lock.h:170
PGPROC * myProc
Definition: lock.h:344
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
Definition: lock.h:347
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define elog(elevel,...)
Definition: elog.h:228
#define InvalidLocalTransactionId
Definition: lock.h:68
int i
PGPROC * allProcs
Definition: proc.h:247
static const LockMethod LockMethods[]
Definition: lock.c:150
uint32 locktag_field1
Definition: lock.h:165
Definition: proc.h:95
#define offsetof(type, field)
Definition: c.h:662
int numLockModes
Definition: lock.h:112

◆ GetLockmodeName()

const char* GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)

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

3926 {
3927  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
3928  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
3929  return LockMethods[lockmethodid]->lockModeNames[mode];
3930 }
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define lengthof(array)
Definition: c.h:669
#define Assert(condition)
Definition: c.h:739
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 460 of file lock.c.

References Assert, lengthof, and LOCK_LOCKMETHOD.

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

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

◆ GetLockStatusData()

LockData* GetLockStatusData ( void  )

Definition at line 3478 of file lock.c.

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

Referenced by pg_lock_status().

3479 {
3480  LockData *data;
3481  PROCLOCK *proclock;
3482  HASH_SEQ_STATUS seqstat;
3483  int els;
3484  int el;
3485  int i;
3486 
3487  data = (LockData *) palloc(sizeof(LockData));
3488 
3489  /* Guess how much space we'll need. */
3490  els = MaxBackends;
3491  el = 0;
3492  data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3493 
3494  /*
3495  * First, we iterate through the per-backend fast-path arrays, locking
3496  * them one at a time. This might produce an inconsistent picture of the
3497  * system state, but taking all of those LWLocks at the same time seems
3498  * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
3499  * matter too much, because none of these locks can be involved in lock
3500  * conflicts anyway - anything that might must be present in the main lock
3501  * table. (For the same reason, we don't sweat about making leaderPid
3502  * completely valid. We cannot safely dereference another backend's
3503  * lockGroupLeader field without holding all lock partition locks, and
3504  * it's not worth that.)
3505  */
3506  for (i = 0; i < ProcGlobal->allProcCount; ++i)
3507  {
3508  PGPROC *proc = &ProcGlobal->allProcs[i];
3509  uint32 f;
3510 
3512 
3513  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
3514  {
3515  LockInstanceData *instance;
3516  uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
3517 
3518  /* Skip unallocated slots. */
3519  if (!lockbits)
3520  continue;
3521 
3522  if (el >= els)
3523  {
3524  els += MaxBackends;
3525  data->locks = (LockInstanceData *)
3526  repalloc(data->locks, sizeof(LockInstanceData) * els);
3527  }
3528 
3529  instance = &data->locks[el];
3530  SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3531  proc->fpRelId[f]);
3532  instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3533  instance->waitLockMode = NoLock;
3534  instance->backend = proc->backendId;
3535  instance->lxid = proc->lxid;
3536  instance->pid = proc->pid;
3537  instance->leaderPid = proc->pid;
3538  instance->fastpath = true;
3539 
3540  el++;
3541  }
3542 
3543  if (proc->fpVXIDLock)
3544  {
3545  VirtualTransactionId vxid;
3546  LockInstanceData *instance;
3547 
3548  if (el >= els)
3549  {
3550  els += MaxBackends;
3551  data->locks = (LockInstanceData *)
3552  repalloc(data->locks, sizeof(LockInstanceData) * els);
3553  }
3554 
3555  vxid.backendId = proc->backendId;
3557 
3558  instance = &data->locks[el];
3559  SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3560  instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3561  instance->waitLockMode = NoLock;
3562  instance->backend = proc->backendId;
3563  instance->lxid = proc->lxid;
3564  instance->pid = proc->pid;
3565  instance->leaderPid = proc->pid;
3566  instance->fastpath = true;
3567 
3568  el++;
3569  }
3570 
3571  LWLockRelease(&proc->backendLock);
3572  }
3573 
3574  /*
3575  * Next, acquire lock on the entire shared lock data structure. We do
3576  * this so that, at least for locks in the primary lock table, the state
3577  * will be self-consistent.
3578  *
3579  * Since this is a read-only operation, we take shared instead of
3580  * exclusive lock. There's not a whole lot of point to this, because all
3581  * the normal operations require exclusive lock, but it doesn't hurt
3582  * anything either. It will at least allow two backends to do
3583  * GetLockStatusData in parallel.
3584  *
3585  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3586  */
3587  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3589 
3590  /* Now we can safely count the number of proclocks */
3592  if (data->nelements > els)
3593  {
3594  els = data->nelements;
3595  data->locks = (LockInstanceData *)
3596  repalloc(data->locks, sizeof(LockInstanceData) * els);
3597  }
3598 
3599  /* Now scan the tables to copy the data */
3601 
3602  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3603  {
3604  PGPROC *proc = proclock->tag.myProc;
3605  LOCK *lock = proclock->tag.myLock;
3606  LockInstanceData *instance = &data->locks[el];
3607 
3608  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3609  instance->holdMask = proclock->holdMask;
3610  if (proc->waitLock == proclock->tag.myLock)
3611  instance->waitLockMode = proc->waitLockMode;
3612  else
3613  instance->waitLockMode = NoLock;
3614  instance->backend = proc->backendId;
3615  instance->lxid = proc->lxid;
3616  instance->pid = proc->pid;
3617  instance->leaderPid = proclock->groupLeader->pid;
3618  instance->fastpath = false;
3619 
3620  el++;
3621  }
3622 
3623  /*
3624  * And release locks. We do this in reverse order for two reasons: (1)
3625  * Anyone else who needs more than one of the locks will be trying to lock
3626  * them in increasing order; we don't want to release the other process
3627  * until it can get all the locks it needs. (2) This avoids O(N^2)
3628  * behavior inside LWLockRelease.
3629  */
3630  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3632 
3633  Assert(el == data->nelements);
3634 
3635  return data;
3636 }
PROCLOCKTAG tag
Definition: lock.h:350
LockInstanceData * locks
Definition: lock.h:444
BackendId backendId
Definition: proc.h:113
#define ExclusiveLock
Definition: lockdefs.h:44
LOCKMASK holdMask
Definition: lock.h:354
bool fastpath
Definition: lock.h:438
LOCKMODE waitLockMode
Definition: proc.h:141
LOCKTAG tag
Definition: lock.h:290
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
Definition: lock.h:163
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1335
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
bool fpVXIDLock
Definition: proc.h:195
Definition: lock.h:441
LocalTransactionId localTransactionId
Definition: lock.h:65
LOCKTAG locktag
Definition: lock.h:431
LOCKMODE waitLockMode
Definition: lock.h:433
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
int leaderPid
Definition: lock.h:437
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:505
int MaxBackends
Definition: globals.c:135
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition: lock.h:180
#define NoLock
Definition: lockdefs.h:34
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:71
Oid databaseId
Definition: proc.h:114
unsigned int uint32
Definition: c.h:359
Definition: lock.h:287
LOCK * waitLock
Definition: proc.h:139
int nelements
Definition: lock.h:443
BackendId backend
Definition: lock.h:434
LocalTransactionId lxid
Definition: lock.h:435
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:194
#define Assert(condition)
Definition: c.h:739
BackendId backendId
Definition: lock.h:64
LWLock backendLock
Definition: proc.h:190
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition: lock.h:225
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
uint32 allProcCount
Definition: proc.h:251
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
LOCKMASK holdMask
Definition: lock.h:432
PGPROC * myProc
Definition: lock.h:344
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:347
void * palloc(Size size)
Definition: mcxt.c:949
int i
LOCK * myLock
Definition: lock.h:343
PGPROC * allProcs
Definition: proc.h:247
Definition: proc.h:95
int pid
Definition: proc.h:109
LocalTransactionId fpLocalTransactionId
Definition: proc.h:196
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
PGPROC * groupLeader
Definition: lock.h:353
LocalTransactionId lxid
Definition: proc.h:106

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)

Definition at line 472 of file lock.c.

References Assert, lengthof, and LOCKTAG::locktag_lockmethodid.

Referenced by pg_blocking_pids().

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

◆ GetRunningTransactionLocks()

xl_standby_lock* GetRunningTransactionLocks ( int *  nlocks)

Definition at line 3842 of file lock.c.

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

Referenced by LogStandbySnapshot().

3843 {
3844  xl_standby_lock *accessExclusiveLocks;
3845  PROCLOCK *proclock;
3846  HASH_SEQ_STATUS seqstat;
3847  int i;
3848  int index;
3849  int els;
3850 
3851  /*
3852  * Acquire lock on the entire shared lock data structure.
3853  *
3854  * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3855  */
3856  for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3858 
3859  /* Now we can safely count the number of proclocks */
3861 
3862  /*
3863  * Allocating enough space for all locks in the lock table is overkill,
3864  * but it's more convenient and faster than having to enlarge the array.
3865  */
3866  accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
3867 
3868  /* Now scan the tables to copy the data */
3870 
3871  /*
3872  * If lock is a currently granted AccessExclusiveLock then it will have
3873  * just one proclock holder, so locks are never accessed twice in this
3874  * particular case. Don't copy this code for use elsewhere because in the
3875  * general case this will give you duplicate locks when looking at
3876  * non-exclusive lock types.
3877  */
3878  index = 0;
3879  while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3880  {
3881  /* make sure this definition matches the one used in LockAcquire */
3882  if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
3883  proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION)
3884  {
3885  PGPROC *proc = proclock->tag.myProc;
3886  PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno];
3887  LOCK *lock = proclock->tag.myLock;
3888  TransactionId xid = pgxact->xid;
3889 
3890  /*
3891  * Don't record locks for transactions if we know they have
3892  * already issued their WAL record for commit but not yet released
3893  * lock. It is still possible that we see locks held by already
3894  * complete transactions, if they haven't yet zeroed their xids.
3895  */
3896  if (!TransactionIdIsValid(xid))
3897  continue;
3898 
3899  accessExclusiveLocks[index].xid = xid;
3900  accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
3901  accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
3902 
3903  index++;
3904  }
3905  }
3906 
3907  Assert(index <= els);
3908 
3909  /*
3910  * And release locks. We do this in reverse order for two reasons: (1)
3911  * Anyone else who needs more than one of the locks will be trying to lock
3912  * them in increasing order; we don't want to release the other process
3913  * until it can get all the locks it needs. (2) This avoids O(N^2)
3914  * behavior inside LWLockRelease.
3915  */
3916  for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3918 
3919  *nlocks = index;
3920  return accessExclusiveLocks;
3921 }
PROCLOCKTAG tag
Definition: lock.h:350
uint32 TransactionId
Definition: c.h:514
Definition: proc.h:222
PGXACT * allPgXact
Definition: proc.h:249
LOCKMASK holdMask
Definition: lock.h:354
TransactionId xid
Definition: proc.h:224
LOCKTAG tag
Definition: lock.h:290
PROC_HDR * ProcGlobal
Definition: proc.c:80
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1335
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:505
uint32 locktag_field2
Definition: lock.h:166
Definition: lock.h:287
TransactionId xid
Definition: lockdefs.h:54
uint8 locktag_type
Definition: lock.h:169
#define Assert(condition)
Definition: c.h:739
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
PGPROC * myProc
Definition: lock.h:344
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
#define AccessExclusiveLock
Definition: lockdefs.h:45
Definition: lock.h:347
int pgprocno
Definition: proc.h:110
void * palloc(Size size)
Definition: mcxt.c:949
int i
LOCK * myLock
Definition: lock.h:343
#define TransactionIdIsValid(xid)
Definition: transam.h:41
uint32 locktag_field1
Definition: lock.h:165
Definition: proc.h:95
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117

◆ GetSingleProcBlockerStatusData()

static void GetSingleProcBlockerStatusData ( PGPROC blocked_proc,
BlockedProcsData data 
)
static

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

3743 {
3744  LOCK *theLock = blocked_proc->waitLock;
3745  BlockedProcData *bproc;
3746  SHM_QUEUE *procLocks;
3747  PROCLOCK *proclock;
3748  PROC_QUEUE *waitQueue;
3749  PGPROC *proc;
3750  int queue_size;
3751  int i;
3752 
3753  /* Nothing to do if this proc is not blocked */
3754  if (theLock == NULL)
3755  return;
3756 
3757  /* Set up a procs[] element */
3758  bproc = &data->procs[data->nprocs++];
3759  bproc->pid = blocked_proc->pid;
3760  bproc->first_lock = data->nlocks;
3761  bproc->first_waiter = data->npids;
3762 
3763  /*
3764  * We may ignore the proc's fast-path arrays, since nothing in those could
3765  * be related to a contended lock.
3766  */
3767 
3768  /* Collect all PROCLOCKs associated with theLock */
3769  procLocks = &(theLock->procLocks);
3770  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3771  offsetof(PROCLOCK, lockLink));
3772  while (proclock)
3773  {
3774  PGPROC *proc = proclock->tag.myProc;
3775  LOCK *lock = proclock->tag.myLock;
3776  LockInstanceData *instance;
3777 
3778  if (data->nlocks >= data->maxlocks)
3779  {
3780  data->maxlocks += MaxBackends;
3781  data->locks = (LockInstanceData *)
3782  repalloc(data->locks, sizeof(LockInstanceData) * data->maxlocks);
3783  }
3784 
3785  instance = &data->locks[data->nlocks];
3786  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3787  instance->holdMask = proclock->holdMask;
3788  if (proc->waitLock == lock)
3789  instance->waitLockMode = proc->waitLockMode;
3790  else
3791  instance->waitLockMode = NoLock;
3792  instance->backend = proc->backendId;
3793  instance->lxid = proc->lxid;
3794  instance->pid = proc->pid;
3795  instance->leaderPid = proclock->groupLeader->pid;
3796  instance->fastpath = false;
3797  data->nlocks++;
3798 
3799  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3800  offsetof(PROCLOCK, lockLink));
3801  }
3802 
3803  /* Enlarge waiter_pids[] if it's too small to hold all wait queue PIDs */
3804  waitQueue = &(theLock->waitProcs);
3805  queue_size = waitQueue->size;
3806 
3807  if (queue_size > data->maxpids - data->npids)
3808  {
3809  data->maxpids = Max(data->maxpids + MaxBackends,
3810  data->npids + queue_size);
3811  data->waiter_pids = (int *) repalloc(data->waiter_pids,
3812  sizeof(int) * data->maxpids);
3813  }
3814 
3815  /* Collect PIDs from the lock's wait queue, stopping at blocked_proc */
3816  proc = (PGPROC *) waitQueue->links.next;
3817  for (i = 0; i < queue_size; i++)
3818  {
3819  if (proc == blocked_proc)
3820  break;
3821  data->waiter_pids[data->npids++] = proc->pid;
3822  proc = (PGPROC *) proc->links.next;
3823  }
3824 
3825  bproc->num_locks = data->nlocks - bproc->first_lock;
3826  bproc->num_waiters = data->npids - bproc->first_waiter;
3827 }
PROCLOCKTAG tag
Definition: lock.h:350
int * waiter_pids
Definition: lock.h:464
BackendId backendId
Definition: proc.h:113
int first_lock
Definition: lock.h:452
SHM_QUEUE links
Definition: lock.h:31
int num_waiters
Definition: lock.h:457
LOCKMASK holdMask
Definition: lock.h:354
SHM_QUEUE links
Definition: proc.h:98
struct SHM_QUEUE * next
Definition: shmem.h:31
bool fastpath
Definition: lock.h:438
LOCKMODE waitLockMode
Definition: proc.h:141
LOCKTAG tag
Definition: lock.h:290
Definition: lock.h:163
SHM_QUEUE lockLink
Definition: lock.h:356
BlockedProcData * procs
Definition: lock.h:462
LOCKTAG locktag
Definition: lock.h:431
LOCKMODE waitLockMode
Definition: lock.h:433
int num_locks
Definition: lock.h:453
PROC_QUEUE waitProcs
Definition: lock.h:296
int leaderPid
Definition: lock.h:437
int MaxBackends
Definition: globals.c:135
#define NoLock
Definition: lockdefs.h:34
Definition: lock.h:287
LOCK * waitLock
Definition: proc.h:139
int maxlocks
Definition: lock.h:468
SHM_QUEUE procLocks
Definition: lock.h:295
LockInstanceData * locks
Definition: lock.h:463
BackendId backend
Definition: lock.h:434
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
int first_waiter
Definition: lock.h:456
#define Max(x, y)
Definition: c.h:905
LocalTransactionId lxid
Definition: lock.h:435
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
LOCKMASK holdMask
Definition: lock.h:432
PGPROC * myProc
Definition: lock.h:344
Definition: lock.h:347
int i
int size
Definition: lock.h:32
LOCK * myLock
Definition: lock.h:343
Definition: proc.h:95
int pid
Definition: proc.h:109
#define offsetof(type, field)
Definition: c.h:662
PGPROC * groupLeader
Definition: lock.h:353
LocalTransactionId lxid
Definition: proc.h:106

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )

Definition at line 1695 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

1696 {
1698 }
static LOCALLOCK * awaitedLock
Definition: lock.c:260
static ResourceOwner awaitedOwner
Definition: lock.c:261
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition: lock.c:1601

◆ GrantLock()

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

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

1468 {
1469  lock->nGranted++;
1470  lock->granted[lockmode]++;
1471  lock->grantMask |= LOCKBIT_ON(lockmode);
1472  if (lock->granted[lockmode] == lock->requested[lockmode])
1473  lock->waitMask &= LOCKBIT_OFF(lockmode);
1474  proclock->holdMask |= LOCKBIT_ON(lockmode);
1475  LOCK_PRINT("GrantLock", lock, lockmode);
1476  Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1477  Assert(lock->nGranted <= lock->nRequested);
1478 }
int nRequested
Definition: lock.h:298
LOCKMASK holdMask
Definition: lock.h:354
int nGranted
Definition: lock.h:300
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:87
int granted[MAX_LOCKMODES]
Definition: lock.h:299
LOCKMASK waitMask
Definition: lock.h:294
int requested[MAX_LOCKMODES]
Definition: lock.h:297
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:739
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:293

◆ GrantLockLocal()

static void GrantLockLocal ( LOCALLOCK locallock,
ResourceOwner  owner 
)
static

Definition at line 1601 of file lock.c.

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

Referenced by GrantAwaitedLock(), and LockAcquireExtended().

1602 {
1603  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1604  int i;
1605 
1606  Assert(locallock->numLockOwners < locallock->maxLockOwners);
1607  /* Count the total */
1608  locallock->nLocks++;
1609  /* Count the per-owner lock */
1610  for (i = 0; i < locallock->numLockOwners; i++)
1611  {
1612  if (lockOwners[i].owner == owner)
1613  {
1614  lockOwners[i].nLocks++;
1615  return;
1616  }
1617  }
1618  lockOwners[i].owner = owner;
1619  lockOwners[i].nLocks = 1;
1620  locallock->numLockOwners++;
1621  if (owner != NULL)
1622  ResourceOwnerRememberLock(owner, locallock);
1623 }
int numLockOwners
Definition: lock.h:414
int64 nLocks
Definition: lock.h:401
int maxLockOwners
Definition: lock.h:415
#define Assert(condition)
Definition: c.h:739
LOCALLOCKOWNER * lockOwners
Definition: lock.h:416
int64 nLocks
Definition: lock.h:413
int i
struct ResourceOwnerData * owner
Definition: lock.h:400
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:933

◆ InitLocks()

void InitLocks ( void  )

Definition at line 377 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

◆ lock_twophase_postabort()

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

Definition at line 4277 of file lock.c.

References lock_twophase_postcommit().

4279 {
4280  lock_twophase_postcommit(xid, info, recdata, len);
4281 }
void lock_twophase_postcommit(TransactionId xid, uint16 info, void *recdata, uint32 len)
Definition: lock.c:4251

◆ lock_twophase_postcommit()

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

Definition at line 4251 of file lock.c.

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

Referenced by lock_twophase_postabort().

4253 {
4254  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4255  PGPROC *proc = TwoPhaseGetDummyProc(xid, true);
4256  LOCKTAG *locktag;
4257  LOCKMETHODID lockmethodid;
4258  LockMethod lockMethodTable;
4259 
4260  Assert(len == sizeof(TwoPhaseLockRecord));
4261  locktag = &rec->locktag;
4262  lockmethodid = locktag->locktag_lockmethodid;
4263 
4264  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4265  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4266  lockMethodTable = LockMethods[lockmethodid];
4267 
4268  LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4269 }
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3042
Definition: lock.h:163
#define lengthof(array)
Definition: c.h:669
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:878
uint16 LOCKMETHODID
Definition: lock.h:124
#define Assert(condition)
Definition: c.h:739
uint8 locktag_lockmethodid
Definition: lock.h:170
#define elog(elevel,...)
Definition: elog.h:228
static const LockMethod LockMethods[]
Definition: lock.c:150
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:95

◆ lock_twophase_recover()

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

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

4040 {
4041  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4042  PGPROC *proc = TwoPhaseGetDummyProc(xid, false);
4043  LOCKTAG *locktag;
4044  LOCKMODE lockmode;
4045  LOCKMETHODID lockmethodid;
4046  LOCK *lock;
4047  PROCLOCK *proclock;
4048  PROCLOCKTAG proclocktag;
4049  bool found;
4050  uint32 hashcode;
4051  uint32 proclock_hashcode;
4052  int partition;
4053  LWLock *partitionLock;
4054  LockMethod lockMethodTable;
4055 
4056  Assert(len == sizeof(TwoPhaseLockRecord));
4057  locktag = &rec->locktag;
4058  lockmode = rec->lockmode;
4059  lockmethodid = locktag->locktag_lockmethodid;
4060 
4061  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4062  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4063  lockMethodTable = LockMethods[lockmethodid];
4064 
4065  hashcode = LockTagHashCode(locktag);
4066  partition = LockHashPartition(hashcode);
4067  partitionLock = LockHashPartitionLock(hashcode);
4068 
4069  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4070 
4071  /*
4072  * Find or create a lock with this tag.
4073  */
4075  (void *) locktag,
4076  hashcode,
4078  &found);
4079  if (!lock)
4080  {
4081  LWLockRelease(partitionLock);
4082  ereport(ERROR,
4083  (errcode(ERRCODE_OUT_OF_MEMORY),
4084  errmsg("out of shared memory"),
4085  errhint("You might need to increase max_locks_per_transaction.")));
4086  }
4087 
4088  /*
4089  * if it's a new lock object, initialize it
4090  */
4091  if (!found)
4092  {
4093  lock->grantMask = 0;
4094  lock->waitMask = 0;
4095  SHMQueueInit(&(lock->procLocks));
4096  ProcQueueInit(&(lock->waitProcs));
4097  lock->nRequested = 0;
4098  lock->nGranted = 0;
4099  MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4100  MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4101  LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4102  }
4103  else
4104  {
4105  LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4106  Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4107  Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4108  Assert(lock->nGranted <= lock->nRequested);
4109  }
4110 
4111  /*
4112  * Create the hash key for the proclock table.
4113  */
4114  proclocktag.myLock = lock;
4115  proclocktag.myProc = proc;
4116 
4117  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4118 
4119  /*
4120  * Find or create a proclock entry with this tag
4121  */
4123  (void *) &proclocktag,
4124  proclock_hashcode,
4126  &found);
4127  if (!proclock)
4128  {
4129  /* Oops, not enough shmem for the proclock */
4130  if (lock->nRequested == 0)
4131  {
4132  /*
4133  * There are no other requestors of this lock, so garbage-collect
4134  * the lock object. We *must* do this to avoid a permanent leak
4135  * of shared memory, because there won't be anything to cause
4136  * anyone to release the lock object later.
4137  */
4138  Assert(SHMQueueEmpty(&(lock->procLocks)));
4140  (void *) &(lock->tag),
4141  hashcode,
4142  HASH_REMOVE,
4143  NULL))
4144  elog(PANIC, "lock table corrupted");
4145  }
4146  LWLockRelease(partitionLock);
4147  ereport(ERROR,
4148  (errcode(ERRCODE_OUT_OF_MEMORY),
4149  errmsg("out of shared memory"),
4150  errhint("You might need to increase max_locks_per_transaction.")));
4151  }
4152 
4153  /*
4154  * If new, initialize the new entry
4155  */
4156  if (!found)
4157  {
4158  Assert(proc->lockGroupLeader == NULL);
4159  proclock->groupLeader = proc;
4160  proclock->holdMask = 0;
4161  proclock->releaseMask = 0;
4162  /* Add proclock to appropriate lists */
4163  SHMQueueInsertBefore(&lock->procLocks, &proclock->lockLink);
4164  SHMQueueInsertBefore(&(proc->myProcLocks[partition]),
4165  &proclock->procLink);
4166  PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4167  }
4168  else
4169  {
4170  PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4171  Assert((proclock->holdMask & ~lock->grantMask) == 0);
4172  }
4173 
4174  /*
4175  * lock->nRequested and lock->requested[] count the total number of
4176  * requests, whether granted or waiting, so increment those immediately.
4177  */
4178  lock->nRequested++;
4179  lock->requested[lockmode]++;
4180  Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4181 
4182  /*
4183  * We shouldn't already hold the desired lock.
4184  */
4185  if (proclock->holdMask & LOCKBIT_ON(lockmode))
4186  elog(ERROR, "lock %s on object %u/%u/%u is already held",
4187  lockMethodTable->lockModeNames[lockmode],
4188  lock->tag.locktag_field1, lock->tag.locktag_field2,
4189  lock->tag.locktag_field3);
4190 
4191  /*
4192  * We ignore any possible conflicts and just grant ourselves the lock. Not
4193  * only because we don't bother, but also to avoid deadlocks when
4194  * switching from standby to normal mode. See function comment.
4195  */
4196  GrantLock(lock, proclock, lockmode);
4197 
4198  /*
4199  * Bump strong lock count, to make sure any fast-path lock requests won't
4200  * be granted without consulting the primary lock table.
4201  */
4202  if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4203  {
4204  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4205 
4207  FastPathStrongRelationLocks->count[fasthashcode]++;
4209  }
4210 
4211  LWLockRelease(partitionLock);
4212 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
Definition: lwlock.h:32
int errhint(const char *fmt,...)
Definition: elog.c:1069
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
int LOCKMODE
Definition: lockdefs.h:26
int nRequested
Definition: lock.h:298
LOCKMASK holdMask
Definition: lock.h:354
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1467
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
LOCKTAG tag
Definition: lock.h:290
Definition: lock.h:163
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
SHM_QUEUE lockLink
Definition: lock.h:356
int errcode(int sqlerrcode)
Definition: elog.c:608
#define MemSet(start, val, len)
Definition: c.h:962
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
#define LockHashPartition(hashcode)
Definition: lock.h:500
void SHMQueueInsertBefore(SHM_QUEUE *queue, SHM_QUEUE *elem)
Definition: shmqueue.c:89
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:669
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:300
PROC_QUEUE waitProcs
Definition: lock.h:296
LOCKTAG locktag
Definition: lock.c:160
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define ERROR
Definition: elog.h:43
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
void ProcQueueInit(PROC_QUEUE *queue)
Definition: proc.c:1038
uint32 locktag_field2
Definition: lock.h:166
unsigned int uint32
Definition: c.h:359
int granted[MAX_LOCKMODES]
Definition: lock.h:299
Definition: lock.h:287
PGPROC * TwoPhaseGetDummyProc(TransactionId xid, bool lock_held)
Definition: twophase.c:878
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define ereport(elevel, rest)
Definition: elog.h:141
LOCKMASK waitMask
Definition: lock.h:294
uint16 LOCKMETHODID
Definition: lock.h:124
SHM_QUEUE procLocks
Definition: lock.h:295
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
#define SpinLockRelease(lock)
Definition: spin.h:64
int requested[MAX_LOCKMODES]
Definition: lock.h:297
#define MAX_LOCKMODES
Definition: lock.h:84
SHM_QUEUE procLink
Definition: lock.h:357
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:739
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
uint8 locktag_lockmethodid
Definition: lock.h:170
PGPROC * myProc
Definition: lock.h:344
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:293
Definition: lock.h:347
int errmsg(const char *fmt,...)
Definition: elog.c:822
void SHMQueueInit(SHM_QUEUE *queue)
Definition: shmqueue.c:36
#define elog(elevel,...)
Definition: elog.h:228
LOCK * myLock
Definition: lock.h:343
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
uint32 locktag_field1
Definition: lock.h:165
LOCKMODE lockmode
Definition: lock.c:161
Definition: proc.h:95
uint32 locktag_field3
Definition: lock.h:167
PGPROC * lockGroupLeader
Definition: proc.h:203
const char *const * lockModeNames
Definition: lock.h:114
PGPROC * groupLeader
Definition: lock.h:353
LOCKMASK releaseMask
Definition: lock.h:355

◆ lock_twophase_standby_recover()

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

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

4221 {
4222  TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4223  LOCKTAG *locktag;
4224  LOCKMODE lockmode;
4225  LOCKMETHODID lockmethodid;
4226 
4227  Assert(len == sizeof(TwoPhaseLockRecord));
4228  locktag = &rec->locktag;
4229  lockmode = rec->lockmode;
4230  lockmethodid = locktag->locktag_lockmethodid;
4231 
4232  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4233  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4234 
4235  if (lockmode == AccessExclusiveLock &&
4236  locktag->locktag_type == LOCKTAG_RELATION)
4237  {
4239  locktag->locktag_field1 /* dboid */ ,
4240  locktag->locktag_field2 /* reloid */ );
4241  }
4242 }
int LOCKMODE
Definition: lockdefs.h:26
Definition: lock.h:163
#define lengthof(array)
Definition: c.h:669
LOCKTAG locktag
Definition: lock.c:160
#define ERROR
Definition: elog.h:43
uint32 locktag_field2
Definition: lock.h:166
uint16 LOCKMETHODID
Definition: lock.h:124
uint8 locktag_type
Definition: lock.h:169
#define Assert(condition)
Definition: c.h:739
uint8 locktag_lockmethodid
Definition: lock.h:170
#define AccessExclusiveLock
Definition: lockdefs.h:45
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition: standby.c:629
#define elog(elevel,...)
Definition: elog.h:228
static const LockMethod LockMethods[]
Definition: lock.c:150
uint32 locktag_field1
Definition: lock.h:165
LOCKMODE lockmode
Definition: lock.c:161

◆ LockAcquire()

◆ LockAcquireExtended()

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

Definition at line 732 of file lock.c.

References AbortStrongLockAcquire(), AccessExclusiveLock, Assert, PGPROC::backendLock, BeginStrongLockAcquire(), ConflictsWithRelationFastPath, LockMethodData::conflictTab, FastPathStrongRelationLockData::count, CurrentResourceOwner, EligibleForRelationFastPath, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FastPathGrantRelationLock(), FastPathLocalUseCount, FastPathStrongLockHashPartition, FastPathTransferRelationLocks(), FinishStrongLockAcquire(), FP_LOCK_SLOTS_PER_BACKEND, GrantLock(), GrantLockLocal(), HASH_ENTER, HASH_REMOVE, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, LOCALLOCK::holdsStrongLockCount, InRecovery, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKACQUIRE_ALREADY_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::locktag_type, LockTagHashCode(), LOG, LogAccessExclusiveLock(), LogAccessExclusiveLockPrepare(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LOCALLOCK::maxLockOwners, MemoryContextAlloc(), MemSet, LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, LOCK::nGranted, LOCALLOCK::nLocks, LOCK::nRequested, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, ProcLockHashCode(), RecoveryInProgress(), RemoveLocalLock(), repalloc(), LOCK::requested, RowExclusiveLock, SetupLockInTable(), SHMQueueDelete(), status(), STATUS_FOUND, STATUS_OK, PROCLOCK::tag, TopMemoryContext, LOCK::waitMask, WaitOnLock(), and XLogStandbyInfoActive.

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

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

◆ LockCheckConflicts()

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

Definition at line 1344 of file lock.c.

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

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

1348 {
1349  int numLockModes = lockMethodTable->numLockModes;
1350  LOCKMASK myLocks;
1351  int conflictMask = lockMethodTable->conflictTab[lockmode];
1352  int conflictsRemaining[MAX_LOCKMODES];
1353  int totalConflictsRemaining = 0;
1354  int i;
1355  SHM_QUEUE *procLocks;
1356  PROCLOCK *otherproclock;
1357 
1358  /*
1359  * first check for global conflicts: If no locks conflict with my request,
1360  * then I get the lock.
1361  *
1362  * Checking for conflict: lock->grantMask represents the types of
1363  * currently held locks. conflictTable[lockmode] has a bit set for each
1364  * type of lock that conflicts with request. Bitwise compare tells if
1365  * there is a conflict.
1366  */
1367  if (!(conflictMask & lock->grantMask))
1368  {
1369  PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1370  return STATUS_OK;
1371  }
1372 
1373  /*
1374  * Rats. Something conflicts. But it could still be my own lock, or a
1375  * lock held by another member of my locking group. First, figure out how
1376  * many conflicts remain after subtracting out any locks I hold myself.
1377  */
1378  myLocks = proclock->holdMask;
1379  for (i = 1; i <= numLockModes; i++)
1380  {
1381  if ((conflictMask & LOCKBIT_ON(i)) == 0)
1382  {
1383  conflictsRemaining[i] = 0;
1384  continue;
1385  }
1386  conflictsRemaining[i] = lock->granted[i];
1387  if (myLocks & LOCKBIT_ON(i))
1388  --conflictsRemaining[i];
1389  totalConflictsRemaining += conflictsRemaining[i];
1390  }
1391 
1392  /* If no conflicts remain, we get the lock. */
1393  if (totalConflictsRemaining == 0)
1394  {
1395  PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1396  return STATUS_OK;
1397  }
1398 
1399  /* If no group locking, it's definitely a conflict. */
1400  if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL)
1401  {
1402  Assert(proclock->tag.myProc == MyProc);
1403  PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1404  proclock);
1405  return STATUS_FOUND;
1406  }
1407 
1408  /*
1409  * Locks held in conflicting modes by members of our own lock group are
1410  * not real conflicts; we can subtract those out and see if we still have
1411  * a conflict. This is O(N) in the number of processes holding or
1412  * awaiting locks on this object. We could improve that by making the
1413  * shared memory state more complex (and larger) but it doesn't seem worth
1414  * it.
1415  */
1416  procLocks = &(lock->procLocks);
1417  otherproclock = (PROCLOCK *)
1418  SHMQueueNext(procLocks, procLocks, offsetof(PROCLOCK, lockLink));
1419  while (otherproclock != NULL)
1420  {
1421  if (proclock != otherproclock &&
1422  proclock->groupLeader == otherproclock->groupLeader &&
1423  (otherproclock->holdMask & conflictMask) != 0)
1424  {
1425  int intersectMask = otherproclock->holdMask & conflictMask;
1426 
1427  for (i = 1; i <= numLockModes; i++)
1428  {
1429  if ((intersectMask & LOCKBIT_ON(i)) != 0)
1430  {
1431  if (conflictsRemaining[i] <= 0)
1432  elog(PANIC, "proclocks held do not match lock");
1433  conflictsRemaining[i]--;
1434  totalConflictsRemaining--;
1435  }
1436  }
1437 
1438  if (totalConflictsRemaining == 0)
1439  {
1440  PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1441  proclock);
1442  return STATUS_OK;
1443  }
1444  }
1445  otherproclock = (PROCLOCK *)
1446  SHMQueueNext(procLocks, &otherproclock->lockLink,
1447  offsetof(PROCLOCK, lockLink));
1448  }
1449 
1450  /* Nope, it's a real conflict. */
1451  PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1452  return STATUS_FOUND;
1453 }
PROCLOCKTAG tag
Definition: lock.h:350
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:354
const LOCKMASK * conflictTab
Definition: lock.h:113
SHM_QUEUE lockLink
Definition: lock.h:356
#define PANIC
Definition: elog.h:53
int granted[MAX_LOCKMODES]
Definition: lock.h:299
#define STATUS_OK
Definition: c.h:1120
SHM_QUEUE procLocks
Definition: lock.h:295
#define MAX_LOCKMODES
Definition: lock.h:84
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
#define Assert(condition)
Definition: c.h:739
#define STATUS_FOUND
Definition: c.h:1123
int LOCKMASK
Definition: lockdefs.h:25
PGPROC * myProc
Definition: lock.h:344
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:293
Definition: lock.h:347
#define elog(elevel,...)
Definition: elog.h:228
int i
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
PGPROC * lockGroupLeader
Definition: proc.h:203
#define offsetof(type, field)
Definition: c.h:662
PGPROC * groupLeader
Definition: lock.h:353
int numLockModes
Definition: lock.h:112

◆ LockHasWaiters()

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

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

596 {
597  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
598  LockMethod lockMethodTable;
599  LOCALLOCKTAG localtag;
600  LOCALLOCK *locallock;
601  LOCK *lock;
602  PROCLOCK *proclock;
603  LWLock *partitionLock;
604  bool hasWaiters = false;
605 
606  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
607  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
608  lockMethodTable = LockMethods[lockmethodid];
609  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
610  elog(ERROR, "unrecognized lock mode: %d", lockmode);
611 
612 #ifdef LOCK_DEBUG
613  if (LOCK_DEBUG_ENABLED(locktag))
614  elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
615  locktag->locktag_field1, locktag->locktag_field2,
616  lockMethodTable->lockModeNames[lockmode]);
617 #endif
618 
619  /*
620  * Find the LOCALLOCK entry for this lock and lockmode
621  */
622  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
623  localtag.lock = *locktag;
624  localtag.mode = lockmode;
625 
626  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
627  (void *) &localtag,
628  HASH_FIND, NULL);
629 
630  /*
631  * let the caller print its own error message, too. Do not ereport(ERROR).
632  */
633  if (!locallock || locallock->nLocks <= 0)
634  {
635  elog(WARNING, "you don't own a lock of type %s",
636  lockMethodTable->lockModeNames[lockmode]);
637  return false;
638  }
639 
640  /*
641  * Check the shared lock table.
642  */
643  partitionLock = LockHashPartitionLock(locallock->hashcode);
644 
645  LWLockAcquire(partitionLock, LW_SHARED);
646 
647  /*
648  * We don't need to re-find the lock or proclock, since we kept their
649  * addresses in the locallock table, and they couldn't have been removed
650  * while we were holding a lock on them.
651  */
652  lock = locallock->lock;
653  LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
654  proclock = locallock->proclock;
655  PROCLOCK_PRINT("LockHasWaiters: found", proclock);
656 
657  /*
658  * Double-check that we are actually holding a lock of the type we want to
659  * release.
660  */
661  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
662  {
663  PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
664  LWLockRelease(partitionLock);
665  elog(WARNING, "you don't own a lock of type %s",
666  lockMethodTable->lockModeNames[lockmode]);
667  RemoveLocalLock(locallock);
668  return false;
669  }
670 
671  /*
672  * Do the checking.
673  */
674  if ((lockMethodTable->conflictTab[lockmode] & lock->waitMask) != 0)
675  hasWaiters = true;
676 
677  LWLockRelease(partitionLock);
678 
679  return hasWaiters;
680 }
uint32 hashcode
Definition: lock.h:410
Definition: lwlock.h:32
static HTAB * LockMethodLocalHash
Definition: lock.c:255
LOCKTAG lock
Definition: lock.h:388
LOCKMODE mode
Definition: lock.h:389
PROCLOCK * proclock
Definition: lock.h:412
LOCKMASK holdMask
Definition: lock.h:354
const LOCKMASK * conflictTab
Definition: lock.h:113
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
#define MemSet(start, val, len)
Definition: c.h:962
#define lengthof(array)
Definition: c.h:669
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define LOG
Definition: elog.h:26
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1296
uint32 locktag_field2
Definition: lock.h:166
Definition: lock.h:287
LOCKMASK waitMask
Definition: lock.h:294
uint16 LOCKMETHODID
Definition: lock.h:124
#define WARNING
Definition: elog.h:40
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
LOCK * lock
Definition: lock.h:411
uint8 locktag_lockmethodid
Definition: lock.h:170
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:347
int64 nLocks
Definition: lock.h:413
#define elog(elevel,...)
Definition: elog.h:228
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
uint32 locktag_field1
Definition: lock.h:165
const char *const * lockModeNames
Definition: lock.h:114
int numLockModes
Definition: lock.h:112

◆ LockHeldByMe()

bool LockHeldByMe ( const LOCKTAG locktag,
LOCKMODE  lockmode 
)

Definition at line 571 of file lock.c.

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

Referenced by CheckRelationLockedByMe().

572 {
573  LOCALLOCKTAG localtag;
574  LOCALLOCK *locallock;
575 
576  /*
577  * See if there is a LOCALLOCK entry for this lock and lockmode
578  */
579  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
580  localtag.lock = *locktag;
581  localtag.mode = lockmode;
582 
583  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
584  (void *) &localtag,
585  HASH_FIND, NULL);
586 
587  return (locallock && locallock->nLocks > 0);
588 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
LOCKTAG lock
Definition: lock.h:388
LOCKMODE mode
Definition: lock.h:389
#define MemSet(start, val, len)
Definition: c.h:962
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
int64 nLocks
Definition: lock.h:413

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2488 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2489 {
2491 
2492  Assert(parent != NULL);
2493 
2494  if (locallocks == NULL)
2495  {
2497  LOCALLOCK *locallock;
2498 
2500 
2501  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2502  LockReassignOwner(locallock, parent);
2503  }
2504  else
2505  {
2506  int i;
2507 
2508  for (i = nlocks - 1; i >= 0; i--)
2509  LockReassignOwner(locallocks[i], parent);
2510  }
2511 }
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition: lock.c:2518
static HTAB * LockMethodLocalHash
Definition: lock.c:255
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition: resowner.c:739
#define Assert(condition)
Definition: c.h:739
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226

◆ LockReassignOwner()

static void LockReassignOwner ( LOCALLOCK locallock,
ResourceOwner  parent 
)
static

Definition at line 2518 of file lock.c.

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

Referenced by LockReassignCurrentOwner().

2519 {
2520  LOCALLOCKOWNER *lockOwners;
2521  int i;
2522  int ic = -1;
2523  int ip = -1;
2524 
2525  /*
2526  * Scan to see if there are any locks belonging to current owner or its
2527  * parent
2528  */
2529  lockOwners = locallock->lockOwners;
2530  for (i = locallock->numLockOwners - 1; i >= 0; i--)
2531  {
2532  if (lockOwners[i].owner == CurrentResourceOwner)
2533  ic = i;
2534  else if (lockOwners[i].owner == parent)
2535  ip = i;
2536  }
2537 
2538  if (ic < 0)
2539  return; /* no current locks */
2540 
2541  if (ip < 0)
2542  {
2543  /* Parent has no slot, so just give it the child's slot */
2544  lockOwners[ic].owner = parent;
2545  ResourceOwnerRememberLock(parent, locallock);
2546  }
2547  else
2548  {
2549  /* Merge child's count with parent's */
2550  lockOwners[ip].nLocks += lockOwners[ic].nLocks;
2551  /* compact out unused slot */
2552  locallock->numLockOwners--;
2553  if (ic < locallock->numLockOwners)
2554  lockOwners[ic] = lockOwners[locallock->numLockOwners];
2555  }
2557 }
int numLockOwners
Definition: lock.h:414
int64 nLocks
Definition: lock.h:401
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:953
LOCALLOCKOWNER * lockOwners
Definition: lock.h:416
int i
struct ResourceOwnerData * owner
Definition: lock.h:400
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:933

◆ LockRefindAndRelease()

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

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

3045 {
3046  LOCK *lock;
3047  PROCLOCK *proclock;
3048  PROCLOCKTAG proclocktag;
3049  uint32 hashcode;
3050  uint32 proclock_hashcode;
3051  LWLock *partitionLock;
3052  bool wakeupNeeded;
3053 
3054  hashcode = LockTagHashCode(locktag);
3055  partitionLock = LockHashPartitionLock(hashcode);
3056 
3057  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3058 
3059  /*
3060  * Re-find the lock object (it had better be there).
3061  */
3063  (void *) locktag,
3064  hashcode,
3065  HASH_FIND,
3066  NULL);
3067  if (!lock)
3068  elog(PANIC, "failed to re-find shared lock object");
3069 
3070  /*
3071  * Re-find the proclock object (ditto).
3072  */
3073  proclocktag.myLock = lock;
3074  proclocktag.myProc = proc;
3075 
3076  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
3077 
3079  (void *) &proclocktag,
3080  proclock_hashcode,
3081  HASH_FIND,
3082  NULL);
3083  if (!proclock)
3084  elog(PANIC, "failed to re-find shared proclock object");
3085 
3086  /*
3087  * Double-check that we are actually holding a lock of the type we want to
3088  * release.
3089  */
3090  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
3091  {
3092  PROCLOCK_PRINT("lock_twophase_postcommit: WRONGTYPE", proclock);
3093  LWLockRelease(partitionLock);
3094  elog(WARNING, "you don't own a lock of type %s",
3095  lockMethodTable->lockModeNames[lockmode]);
3096  return;
3097  }
3098 
3099  /*
3100  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
3101  */
3102  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
3103 
3104  CleanUpLock(lock, proclock,
3105  lockMethodTable, hashcode,
3106  wakeupNeeded);
3107 
3108  LWLockRelease(partitionLock);
3109 
3110  /*
3111  * Decrement strong lock count. This logic is needed only for 2PC.
3112  */
3113  if (decrement_strong_lock_count
3114  && ConflictsWithRelationFastPath(locktag, lockmode))
3115  {
3116  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
3117 
3119  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
3120  FastPathStrongRelationLocks->count[fasthashcode]--;
3122  }
3123 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
Definition: lwlock.h:32
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
LOCKMASK holdMask
Definition: lock.h:354
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
#define FastPathStrongLockHashPartition(hashcode)
Definition: lock.c:235
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define SpinLockAcquire(lock)
Definition: spin.h:62
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition: lock.c:244
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition: lock.c:538
unsigned int uint32
Definition: c.h:359
Definition: lock.h:287
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define WARNING
Definition: elog.h:40
#define SpinLockRelease(lock)
Definition: spin.h:64
#define Assert(condition)
Definition: c.h:739
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
PGPROC * myProc
Definition: lock.h:344
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:347
#define elog(elevel,...)
Definition: elog.h:228
LOCK * myLock
Definition: lock.h:343
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1490
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1547
const char *const * lockModeNames
Definition: lock.h:114

◆ LockRelease()

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

Definition at line 1884 of file lock.c.

References Assert, PGPROC::backendLock, CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FastPathLocalUseCount, FastPathUnGrantRelationLock(), HASH_FIND, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PROCLOCK::holdMask, i, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKBIT_ON, 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().

1885 {
1886  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
1887  LockMethod lockMethodTable;
1888  LOCALLOCKTAG localtag;
1889  LOCALLOCK *locallock;
1890  LOCK *lock;
1891  PROCLOCK *proclock;
1892  LWLock *partitionLock;
1893  bool wakeupNeeded;
1894 
1895  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
1896  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
1897  lockMethodTable = LockMethods[lockmethodid];
1898  if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
1899  elog(ERROR, "unrecognized lock mode: %d", lockmode);
1900 
1901 #ifdef LOCK_DEBUG
1902  if (LOCK_DEBUG_ENABLED(locktag))
1903  elog(LOG, "LockRelease: lock [%u,%u] %s",
1904  locktag->locktag_field1, locktag->locktag_field2,
1905  lockMethodTable->lockModeNames[lockmode]);
1906 #endif
1907 
1908  /*
1909  * Find the LOCALLOCK entry for this lock and lockmode
1910  */
1911  MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
1912  localtag.lock = *locktag;
1913  localtag.mode = lockmode;
1914 
1915  locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
1916  (void *) &localtag,
1917  HASH_FIND, NULL);
1918 
1919  /*
1920  * let the caller print its own error message, too. Do not ereport(ERROR).
1921  */
1922  if (!locallock || locallock->nLocks <= 0)
1923  {
1924  elog(WARNING, "you don't own a lock of type %s",
1925  lockMethodTable->lockModeNames[lockmode]);
1926  return false;
1927  }
1928 
1929  /*
1930  * Decrease the count for the resource owner.
1931  */
1932  {
1933  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1934  ResourceOwner owner;
1935  int i;
1936 
1937  /* Identify owner for lock */
1938  if (sessionLock)
1939  owner = NULL;
1940  else
1941  owner = CurrentResourceOwner;
1942 
1943  for (i = locallock->numLockOwners - 1; i >= 0; i--)
1944  {
1945  if (lockOwners[i].owner == owner)
1946  {
1947  Assert(lockOwners[i].nLocks > 0);
1948  if (--lockOwners[i].nLocks == 0)
1949  {
1950  if (owner != NULL)
1951  ResourceOwnerForgetLock(owner, locallock);
1952  /* compact out unused slot */
1953  locallock->numLockOwners--;
1954  if (i < locallock->numLockOwners)
1955  lockOwners[i] = lockOwners[locallock->numLockOwners];
1956  }
1957  break;
1958  }
1959  }
1960  if (i < 0)
1961  {
1962  /* don't release a lock belonging to another owner */
1963  elog(WARNING, "you don't own a lock of type %s",
1964  lockMethodTable->lockModeNames[lockmode]);
1965  return false;
1966  }
1967  }
1968 
1969  /*
1970  * Decrease the total local count. If we're still holding the lock, we're
1971  * done.
1972  */
1973  locallock->nLocks--;
1974 
1975  if (locallock->nLocks > 0)
1976  return true;
1977 
1978  /*
1979  * At this point we can no longer suppose we are clear of invalidation
1980  * messages related to this lock. Although we'll delete the LOCALLOCK
1981  * object before any intentional return from this routine, it seems worth
1982  * the trouble to explicitly reset lockCleared right now, just in case
1983  * some error prevents us from deleting the LOCALLOCK.
1984  */
1985  locallock->lockCleared = false;
1986 
1987  /* Attempt fast release of any lock eligible for the fast path. */
1988  if (EligibleForRelationFastPath(locktag, lockmode) &&
1990  {
1991  bool released;
1992 
1993  /*
1994  * We might not find the lock here, even if we originally entered it
1995  * here. Another backend may have moved it to the main table.
1996  */
1998  released = FastPathUnGrantRelationLock(locktag->locktag_field2,
1999  lockmode);
2001  if (released)
2002  {
2003  RemoveLocalLock(locallock);
2004  return true;
2005  }
2006  }
2007 
2008  /*
2009  * Otherwise we've got to mess with the shared lock table.
2010  */
2011  partitionLock = LockHashPartitionLock(locallock->hashcode);
2012 
2013  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2014 
2015  /*
2016  * Normally, we don't need to re-find the lock or proclock, since we kept
2017  * their addresses in the locallock table, and they couldn't have been
2018  * removed while we were holding a lock on them. But it's possible that
2019  * the lock was taken fast-path and has since been moved to the main hash
2020  * table by another backend, in which case we will need to look up the
2021  * objects here. We assume the lock field is NULL if so.
2022  */
2023  lock = locallock->lock;
2024  if (!lock)
2025  {
2026  PROCLOCKTAG proclocktag;
2027 
2028  Assert(EligibleForRelationFastPath(locktag, lockmode));
2030  (const void *) locktag,
2031  locallock->hashcode,
2032  HASH_FIND,
2033  NULL);
2034  if (!lock)
2035  elog(ERROR, "failed to re-find shared lock object");
2036  locallock->lock = lock;
2037 
2038  proclocktag.myLock = lock;
2039  proclocktag.myProc = MyProc;
2041  (void *) &proclocktag,
2042  HASH_FIND,
2043  NULL);
2044  if (!locallock->proclock)
2045  elog(ERROR, "failed to re-find shared proclock object");
2046  }
2047  LOCK_PRINT("LockRelease: found", lock, lockmode);
2048  proclock = locallock->proclock;
2049  PROCLOCK_PRINT("LockRelease: found", proclock);
2050 
2051  /*
2052  * Double-check that we are actually holding a lock of the type we want to
2053  * release.
2054  */
2055  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2056  {
2057  PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
2058  LWLockRelease(partitionLock);
2059  elog(WARNING, "you don't own a lock of type %s",
2060  lockMethodTable->lockModeNames[lockmode]);
2061  RemoveLocalLock(locallock);
2062  return false;
2063  }
2064 
2065  /*
2066  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2067  */
2068  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2069 
2070  CleanUpLock(lock, proclock,
2071  lockMethodTable, locallock->hashcode,
2072  wakeupNeeded);
2073 
2074  LWLockRelease(partitionLock);
2075 
2076  RemoveLocalLock(locallock);
2077  return true;
2078 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
uint32 hashcode
Definition: lock.h:410
Definition: lwlock.h:32
static HTAB * LockMethodLocalHash
Definition: lock.c:255
int numLockOwners
Definition: lock.h:414
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2601
LOCKTAG lock
Definition: lock.h:388
LOCKMODE mode
Definition: lock.h:389
PROCLOCK * proclock
Definition: lock.h:412
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:354
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
static int FastPathLocalUseCount
Definition: lock.c:171
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
#define MemSet(start, val, len)
Definition: c.h:962
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
#define lengthof(array)
Definition: c.h:669
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:906
#define LOG
Definition: elog.h:26
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:199
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1296
uint32 locktag_field2
Definition: lock.h:166
Definition: lock.h:287
uint16 LOCKMETHODID
Definition: lock.h:124
#define WARNING
Definition: elog.h:40
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:953
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:739
LWLock backendLock
Definition: proc.h:190
static HTAB * LockMethodLockHash
Definition: lock.c:253
LOCALLOCKOWNER * lockOwners
Definition: lock.h:416
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
LOCK * lock
Definition: lock.h:411
uint8 locktag_lockmethodid
Definition: lock.h:170
PGPROC * myProc
Definition: lock.h:344
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
Definition: lock.h:347
int64 nLocks
Definition: lock.h:413
#define elog(elevel,...)
Definition: elog.h:228
int i
LOCK * myLock
Definition: lock.h:343
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1490
static const LockMethod LockMethods[]
Definition: lock.c:150
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1547
uint32 locktag_field1
Definition: lock.h:165
bool lockCleared
Definition: lock.h:418
const char *const * lockModeNames
Definition: lock.h:114
int numLockModes
Definition: lock.h:112

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)

Definition at line 2089 of file lock.c.

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

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

2090 {
2092  LockMethod lockMethodTable;
2093  int i,
2094  numLockModes;
2095  LOCALLOCK *locallock;
2096  LOCK *lock;
2097  PROCLOCK *proclock;
2098  int partition;
2099  bool have_fast_path_lwlock = false;
2100 
2101  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2102  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2103  lockMethodTable = LockMethods[lockmethodid];
2104 
2105 #ifdef LOCK_DEBUG
2106  if (*(lockMethodTable->trace_flag))
2107  elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2108 #endif
2109 
2110  /*
2111  * Get rid of our fast-path VXID lock, if appropriate. Note that this is
2112  * the only way that the lock we hold on our own VXID can ever get
2113  * released: it is always and only released when a toplevel transaction
2114  * ends.
2115  */
2116  if (lockmethodid == DEFAULT_LOCKMETHOD)
2118 
2119  numLockModes = lockMethodTable->numLockModes;
2120 
2121  /*
2122  * First we run through the locallock table and get rid of unwanted
2123  * entries, then we scan the process's proclocks and get rid of those. We
2124  * do this separately because we may have multiple locallock entries
2125  * pointing to the same proclock, and we daren't end up with any dangling
2126  * pointers. Fast-path locks are cleaned up during the locallock table
2127  * scan, though.
2128  */
2130 
2131  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2132  {
2133  /*
2134  * If the LOCALLOCK entry is unused, we must've run out of shared
2135  * memory while trying to set up this lock. Just forget the local
2136  * entry.
2137  */
2138  if (locallock->nLocks == 0)
2139  {
2140  RemoveLocalLock(locallock);
2141  continue;
2142  }
2143 
2144  /* Ignore items that are not of the lockmethod to be removed */
2145  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2146  continue;
2147 
2148  /*
2149  * If we are asked to release all locks, we can just zap the entry.
2150  * Otherwise, must scan to see if there are session locks. We assume
2151  * there is at most one lockOwners entry for session locks.
2152  */
2153  if (!allLocks)
2154  {
2155  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2156 
2157  /* If session lock is above array position 0, move it down to 0 */
2158  for (i = 0; i < locallock->numLockOwners; i++)
2159  {
2160  if (lockOwners[i].owner == NULL)
2161  lockOwners[0] = lockOwners[i];
2162  else
2163  ResourceOwnerForgetLock(lockOwners[i].owner, locallock);
2164  }
2165 
2166  if (locallock->numLockOwners > 0 &&
2167  lockOwners[0].owner == NULL &&
2168  lockOwners[0].nLocks > 0)
2169  {
2170  /* Fix the locallock to show just the session locks */
2171  locallock->nLocks = lockOwners[0].nLocks;
2172  locallock->numLockOwners = 1;
2173  /* We aren't deleting this locallock, so done */
2174  continue;
2175  }
2176  else
2177  locallock->numLockOwners = 0;
2178  }
2179 
2180  /*
2181  * If the lock or proclock pointers are NULL, this lock was taken via
2182  * the relation fast-path (and is not known to have been transferred).
2183  */
2184  if (locallock->proclock == NULL || locallock->lock == NULL)
2185  {
2186  LOCKMODE lockmode = locallock->tag.mode;
2187  Oid relid;
2188 
2189  /* Verify that a fast-path lock is what we've got. */
2190  if (!EligibleForRelationFastPath(&locallock->tag.lock, lockmode))
2191  elog(PANIC, "locallock table corrupted");
2192 
2193  /*
2194  * If we don't currently hold the LWLock that protects our
2195  * fast-path data structures, we must acquire it before attempting
2196  * to release the lock via the fast-path. We will continue to
2197  * hold the LWLock until we're done scanning the locallock table,
2198  * unless we hit a transferred fast-path lock. (XXX is this
2199  * really such a good idea? There could be a lot of entries ...)
2200  */
2201  if (!have_fast_path_lwlock)
2202  {
2204  have_fast_path_lwlock = true;
2205  }
2206 
2207  /* Attempt fast-path release. */
2208  relid = locallock->tag.lock.locktag_field2;
2209  if (FastPathUnGrantRelationLock(relid, lockmode))
2210  {
2211  RemoveLocalLock(locallock);
2212  continue;
2213  }
2214 
2215  /*
2216  * Our lock, originally taken via the fast path, has been
2217  * transferred to the main lock table. That's going to require
2218  * some extra work, so release our fast-path lock before starting.
2219  */
2221  have_fast_path_lwlock = false;
2222 
2223  /*
2224  * Now dump the lock. We haven't got a pointer to the LOCK or
2225  * PROCLOCK in this case, so we have to handle this a bit
2226  * differently than a normal lock release. Unfortunately, this
2227  * requires an extra LWLock acquire-and-release cycle on the
2228  * partitionLock, but hopefully it shouldn't happen often.
2229  */
2230  LockRefindAndRelease(lockMethodTable, MyProc,
2231  &locallock->tag.lock, lockmode, false);
2232  RemoveLocalLock(locallock);
2233  continue;
2234  }
2235 
2236  /* Mark the proclock to show we need to release this lockmode */
2237  if (locallock->nLocks > 0)
2238  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
2239 
2240  /* And remove the locallock hashtable entry */
2241  RemoveLocalLock(locallock);
2242  }
2243 
2244  /* Done with the fast-path data structures */
2245  if (have_fast_path_lwlock)
2247 
2248  /*
2249  * Now, scan each lock partition separately.
2250  */
2251  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
2252  {
2253  LWLock *partitionLock;
2254  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
2255  PROCLOCK *nextplock;
2256 
2257  partitionLock = LockHashPartitionLockByIndex(partition);
2258 
2259  /*
2260  * If the proclock list for this partition is empty, we can skip
2261  * acquiring the partition lock. This optimization is trickier than
2262  * it looks, because another backend could be in process of adding
2263  * something to our proclock list due to promoting one of our
2264  * fast-path locks. However, any such lock must be one that we
2265  * decided not to delete above, so it's okay to skip it again now;
2266  * we'd just decide not to delete it again. We must, however, be
2267  * careful to re-fetch the list header once we've acquired the
2268  * partition lock, to be sure we have a valid, up-to-date pointer.
2269  * (There is probably no significant risk if pointer fetch/store is
2270  * atomic, but we don't wish to assume that.)
2271  *
2272  * XXX This argument assumes that the locallock table correctly
2273  * represents all of our fast-path locks. While allLocks mode
2274  * guarantees to clean up all of our normal locks regardless of the
2275  * locallock situation, we lose that guarantee for fast-path locks.
2276  * This is not ideal.
2277  */
2278  if (SHMQueueNext(procLocks, procLocks,
2279  offsetof(PROCLOCK, procLink)) == NULL)
2280  continue; /* needn't examine this partition */
2281 
2282  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2283 
2284  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
2285  offsetof(PROCLOCK, procLink));
2286  proclock;
2287  proclock = nextplock)
2288  {
2289  bool wakeupNeeded = false;
2290 
2291  /* Get link first, since we may unlink/delete this proclock */
2292  nextplock = (PROCLOCK *)
2293  SHMQueueNext(procLocks, &proclock->procLink,
2294  offsetof(PROCLOCK, procLink));
2295 
2296  Assert(proclock->tag.myProc == MyProc);
2297 
2298  lock = proclock->tag.myLock;
2299 
2300  /* Ignore items that are not of the lockmethod to be removed */
2301  if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
2302  continue;
2303 
2304  /*
2305  * In allLocks mode, force release of all locks even if locallock
2306  * table had problems
2307  */
2308  if (allLocks)
2309  proclock->releaseMask = proclock->holdMask;
2310  else
2311  Assert((proclock->releaseMask & ~proclock->holdMask) == 0);
2312 
2313  /*
2314  * Ignore items that have nothing to be released, unless they have
2315  * holdMask == 0 and are therefore recyclable
2316  */
2317  if (proclock->releaseMask == 0 && proclock->holdMask != 0)
2318  continue;
2319 
2320  PROCLOCK_PRINT("LockReleaseAll", proclock);
2321  LOCK_PRINT("LockReleaseAll", lock, 0);
2322  Assert(lock->nRequested >= 0);
2323  Assert(lock->nGranted >= 0);
2324  Assert(lock->nGranted <= lock->nRequested);
2325  Assert((proclock->holdMask & ~lock->grantMask) == 0);
2326 
2327  /*
2328  * Release the previously-marked lock modes
2329  */
2330  for (i = 1; i <= numLockModes; i++)
2331  {
2332  if (proclock->releaseMask & LOCKBIT_ON(i))
2333  wakeupNeeded |= UnGrantLock(lock, i, proclock,
2334  lockMethodTable);
2335  }
2336  Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
2337  Assert(lock->nGranted <= lock->nRequested);
2338  LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2339 
2340  proclock->releaseMask = 0;
2341 
2342  /* CleanUpLock will wake up waiters if needed. */
2343  CleanUpLock(lock, proclock,
2344  lockMethodTable,
2345  LockTagHashCode(&lock->tag),
2346  wakeupNeeded);
2347  } /* loop over PROCLOCKs within this partition */
2348 
2349  LWLockRelease(partitionLock);
2350  } /* loop over partitions */
2351 
2352 #ifdef LOCK_DEBUG
2353  if (*(lockMethodTable->trace_flag))
2354  elog(LOG, "LockReleaseAll done");
2355 #endif
2356 }
PROCLOCKTAG tag
Definition: lock.h:350
Definition: lwlock.h:32
LOCALLOCKTAG tag
Definition: lock.h:407
static HTAB * LockMethodLocalHash
Definition: lock.c:255
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition: lock.c:3042
void VirtualXactLockTableCleanup(void)
Definition: lock.c:4324
int numLockOwners
Definition: lock.h:414
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition: lock.c:2601
LOCKTAG lock
Definition: lock.h:388
int LOCKMODE
Definition: lockdefs.h:26
LOCKMODE mode
Definition: lock.h:389
PROCLOCK * proclock
Definition: lock.h:412
int nRequested
Definition: lock.h:298
PGPROC * MyProc
Definition: proc.c:67
LOCKMASK holdMask
Definition: lock.h:354
int64 nLocks
Definition: lock.h:401
LOCKTAG tag
Definition: lock.h:290
#define lengthof(array)
Definition: c.h:669
#define LOG
Definition: elog.h:26
unsigned int Oid
Definition: postgres_ext.h:31
#define EligibleForRelationFastPath(locktag, mode)
Definition: lock.c:199
#define PANIC
Definition: elog.h:53
int nGranted
Definition: lock.h:300
#define DEFAULT_LOCKMETHOD
Definition: lock.h:127
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define LockHashPartitionLockByIndex(i)
Definition: lock.h:505
#define ERROR
Definition: elog.h:43
static void RemoveLocalLock(LOCALLOCK *locallock)
Definition: lock.c:1296
uint32 locktag_field2
Definition: lock.h:166
Definition: lock.h:287
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:421
SHM_QUEUE procLink
Definition: lock.h:357
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:953
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define Assert(condition)
Definition: c.h:739
LWLock backendLock
Definition: proc.h:190
LOCALLOCKOWNER * lockOwners
Definition: lock.h:416
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
LOCK * lock
Definition: lock.h:411
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
PGPROC * myProc
Definition: lock.h:344
#define LOCKBIT_ON(lockmode)
Definition: lock.h:86
LOCKMASK grantMask
Definition: lock.h:293
Definition: lock.h:347
int64 nLocks
Definition: lock.h:413
#define elog(elevel,...)
Definition: elog.h:228
int i
const bool * trace_flag
Definition: lock.h:115
LOCK * myLock
Definition: lock.h:343
struct ResourceOwnerData * owner
Definition: lock.h:400
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1490
static const LockMethod LockMethods[]
Definition: lock.c:150
SHM_QUEUE myProcLocks[NUM_LOCK_PARTITIONS]
Definition: proc.h:160
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1547
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
#define offsetof(type, field)
Definition: c.h:662
#define NUM_LOCK_PARTITIONS
Definition: lwlock.h:117
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:303
int numLockModes
Definition: lock.h:112
LOCKMASK releaseMask
Definition: lock.h:355

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)

Definition at line 2393 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

2394 {
2395  if (locallocks == NULL)
2396  {
2398  LOCALLOCK *locallock;
2399 
2401 
2402  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2403  ReleaseLockIfHeld(locallock, false);
2404  }
2405  else
2406  {
2407  int i;
2408 
2409  for (i = nlocks - 1; i >= 0; i--)
2410  ReleaseLockIfHeld(locallocks[i], false);
2411  }
2412 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2428
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)

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

2364 {
2366  LOCALLOCK *locallock;
2367 
2368  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2369  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2370 
2372 
2373  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2374  {
2375  /* Ignore items that are not of the specified lock method */
2376  if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
2377  continue;
2378 
2379  ReleaseLockIfHeld(locallock, true);
2380  }
2381 }
static HTAB * LockMethodLocalHash
Definition: lock.c:255
#define lengthof(array)
Definition: c.h:669
#define ERROR
Definition: elog.h:43
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition: lock.c:2428
#define LOCALLOCK_LOCKMETHOD(llock)
Definition: lock.h:421
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1389
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1379
#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:226

◆ LockShmemSize()

Size LockShmemSize ( void  )

Definition at line 3441 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

3442 {
3443  Size size = 0;
3444  long max_table_size;
3445 
3446  /* lock hash table */
3447  max_table_size = NLOCKENTS();
3448  size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3449 
3450  /* proclock hash table */
3451  max_table_size *= 2;
3452  size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3453 
3454  /*
3455  * Since NLOCKENTS is only an estimate, add 10% safety margin.
3456  */
3457  size = add_size(size, size / 10);
3458 
3459  return size;
3460 }
#define NLOCKENTS()
Definition: lock.c:56
Definition: lock.h:287
Size hash_estimate_size(long num_entries, Size entrysize)
Definition: dynahash.c:732
Size add_size(Size s1, Size s2)
Definition: shmem.c:475
size_t Size
Definition: c.h:467
Definition: lock.h:347

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)

Definition at line 490 of file lock.c.

References get_hash_value().

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

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)

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

4468 {
4469  LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4470  LOCK *lock;
4471  bool found;
4472  uint32 hashcode;
4473  LWLock *partitionLock;
4474  int waiters = 0;
4475 
4476  if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4477  elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4478 
4479  hashcode = LockTagHashCode(locktag);
4480  partitionLock = LockHashPartitionLock(hashcode);
4481  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4482 
4484  (const void *) locktag,
4485  hashcode,
4486  HASH_FIND,
4487  &found);
4488  if (found)
4489  {
4490  Assert(lock != NULL);
4491  waiters = lock->nRequested;
4492  }
4493  LWLockRelease(partitionLock);
4494 
4495  return waiters;
4496 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:919
Definition: lwlock.h:32
int nRequested
Definition: lock.h:298
#define LockHashPartitionLock(hashcode)
Definition: lock.h:502
#define lengthof(array)
Definition: c.h:669
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1726
#define ERROR
Definition: elog.h:43
unsigned int uint32
Definition: c.h:359
Definition: lock.h:287
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
uint16 LOCKMETHODID
Definition: lock.h:124
#define Assert(condition)
Definition: c.h:739
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1122
uint8 locktag_lockmethodid
Definition: lock.h:170
#define elog(elevel,...)
Definition: elog.h:228
static const LockMethod LockMethods[]
Definition: lock.c:150

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)

Definition at line 1708 of file lock.c.

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

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

1709 {
1710  Assert(locallock->nLocks > 0);
1711  locallock->lockCleared = true;
1712 }
#define Assert(condition)
Definition: c.h:739
int64 nLocks
Definition: lock.h:413
bool lockCleared
Definition: lock.h:418

◆ PostPrepare_Locks()

void PostPrepare_Locks ( TransactionId  xid)

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

3250 {
3251  PGPROC *newproc = TwoPhaseGetDummyProc(xid, false);
3253  LOCALLOCK *locallock;
3254  LOCK *lock;
3255  PROCLOCK *proclock;
3256  PROCLOCKTAG proclocktag;
3257  int partition;
3258 
3259  /* Can't prepare a lock group follower. */
3260  Assert(MyProc->lockGroupLeader == NULL ||
3262 
3263  /* This is a critical section: any error means big trouble */
3265 
3266  /*
3267  * First we run through the locallock table and get rid of unwanted
3268  * entries, then we scan the process's proclocks and transfer them to the
3269  * target proc.
3270  *
3271  * We do this separately because we may have multiple locallock entries
3272  * pointing to the same proclock, and we daren't end up with any dangling
3273  * pointers.
3274  */
3276 
3277  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3278  {
3279  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3280  bool haveSessionLock;
3281  bool haveXactLock;
3282  int i;
3283 
3284  if (locallock->proclock == NULL || locallock->lock == NULL)
3285  {
3286  /*
3287  * We must've run out of shared memory while trying to set up this
3288  * lock. Just forget the local entry.
3289  */
3290  Assert(locallock->nLocks == 0);
3291  RemoveLocalLock(locallock);
3292  continue;
3293  }
3294 
3295  /* Ignore VXID locks */
3296  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3297  continue;
3298 
3299  /* Scan to see whether we hold it at session or transaction level */
3300  haveSessionLock = haveXactLock = false;
3301  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3302  {
3303  if (lockOwners[i].owner == NULL)
3304  haveSessionLock = true;
3305  else
3306  haveXactLock = true;
3307  }
3308 
3309  /* Ignore it if we have only session lock */
3310  if (!haveXactLock)
3311  continue;
3312 
3313  /* This can't happen, because we already checked it */
3314  if (haveSessionLock)
3315  ereport(PANIC,
3316  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3317  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3318 
3319  /* Mark the proclock to show we need to release this lockmode */
3320  if (locallock->nLocks > 0)
3321  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3322 
3323  /* And remove the locallock hashtable entry */
3324  RemoveLocalLock(locallock);
3325  }
3326 
3327  /*
3328  * Now, scan each lock partition separately.
3329  */
3330  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3331  {
3332  LWLock *partitionLock;
3333  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
3334  PROCLOCK *nextplock;
3335 
3336  partitionLock = LockHashPartitionLockByIndex(partition);
3337 
3338  /*
3339  * If the proclock list for this partition is empty, we can skip
3340  * acquiring the partition lock. This optimization is safer than the
3341  * situation in LockReleaseAll, because we got rid of any fast-path
3342  * locks during AtPrepare_Locks, so there cannot be any case where
3343  * another backend is adding something to our lists now. For safety,
3344  * though, we code this the same way as in LockReleaseAll.
3345  */
3346  if (SHMQueueNext(procLocks, procLocks,
3347  offsetof(PROCLOCK, procLink)) == NULL)
3348  continue; /* needn't examine this partition */
3349 
3350  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3351 
3352  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3353