PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 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)
 
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 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)
 
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
FastPathStrongRelationLockData
FastPathStrongRelationLocks
 
static HTABLockMethodLockHash
 
static HTABLockMethodProcLockHash
 
static HTABLockMethodLocalHash
 
static LOCALLOCKStrongLockInProgress
 
static LOCALLOCKawaitedLock
 
static ResourceOwner awaitedOwner
 

Macro Definition Documentation

#define ConflictsWithRelationFastPath (   locktag,
  mode 
)
Value:
((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
(locktag)->locktag_type == LOCKTAG_RELATION && \
(locktag)->locktag_field1 != InvalidOid && \
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
#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().

#define EligibleForRelationFastPath (   locktag,
  mode 
)
Value:
((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
(locktag)->locktag_type == LOCKTAG_RELATION && \
(locktag)->locktag_field1 == MyDatabaseId && \
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
Oid MyDatabaseId
Definition: globals.c:77
#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().

#define FAST_PATH_BIT_POSITION (   n,
 
)
Value:
#define AssertMacro(condition)
Definition: c.h:677
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
#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.

#define FAST_PATH_BITS_PER_SLOT   3

Definition at line 174 of file lock.c.

Referenced by FastPathTransferRelationLocks().

#define FAST_PATH_CHECK_LOCKMODE (   proc,
  n,
 
)    ((proc)->fpLockBits & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))
#define FAST_PATH_CLEAR_LOCKMODE (   proc,
  n,
 
)    (proc)->fpLockBits &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))
#define FAST_PATH_GET_BITS (   proc,
 
)    (((proc)->fpLockBits >> (FAST_PATH_BITS_PER_SLOT * n)) & FAST_PATH_MASK)
#define FAST_PATH_LOCKNUMBER_OFFSET   1

Definition at line 175 of file lock.c.

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

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

Definition at line 176 of file lock.c.

#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().

#define FAST_PATH_STRONG_LOCK_HASH_BITS   10

Definition at line 232 of file lock.c.

#define FAST_PATH_STRONG_LOCK_HASH_PARTITIONS   (1 << FAST_PATH_STRONG_LOCK_HASH_BITS)

Definition at line 233 of file lock.c.

#define FastPathStrongLockHashPartition (   hashcode)    ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS)
#define LOCK_PRINT (   where,
  lock,
  type 
)    ((void) 0)

Definition at line 56 of file lock.c.

Referenced by InitLocks(), and LockShmemSize().

#define PROCLOCK_PRINT (   where,
  proclockP 
)    ((void) 0)

Typedef Documentation

Function Documentation

void AbortStrongLockAcquire ( void  )

Definition at line 1614 of file lock.c.

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

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

Definition at line 3059 of file lock.c.

References ereport, errcode(), errmsg(), ERROR, FALSE, 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, NULL, LOCALLOCK::numLockOwners, LOCALLOCK::proclock, RegisterTwoPhaseRecord(), status(), PROCLOCK::tag, LOCALLOCK::tag, and TWOPHASE_RM_LOCK_ID.

Referenced by PrepareTransaction().

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

Definition at line 1578 of file lock.c.

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

Referenced by LockAcquireExtended().

1579 {
1581  Assert(locallock->holdsStrongLockCount == FALSE);
1582 
1583  /*
1584  * Adding to a memory location is not atomic, so we take a spinlock to
1585  * ensure we don't collide with someone else trying to bump the count at
1586  * the same time.
1587  *
1588  * XXX: It might be worth considering using an atomic fetch-and-add
1589  * instruction here, on architectures where that is supported.
1590  */
1591 
1593  FastPathStrongRelationLocks->count[fasthashcode]++;
1594  locallock->holdsStrongLockCount = TRUE;
1595  StrongLockInProgress = locallock;
1597 }
bool holdsStrongLockCount
Definition: lock.h:413
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 FALSE
Definition: c.h:221
#define SpinLockRelease(lock)
Definition: spin.h:64
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#define TRUE
Definition: c.h:217
static void CleanUpLock ( LOCK lock,
PROCLOCK proclock,
LockMethod  lockMethodTable,
uint32  hashcode,
bool  wakeupNeeded 
)
static

Definition at line 1495 of file lock.c.

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

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

1498 {
1499  /*
1500  * If this was my last hold on this lock, delete my entry in the proclock
1501  * table.
1502  */
1503  if (proclock->holdMask == 0)
1504  {
1505  uint32 proclock_hashcode;
1506 
1507  PROCLOCK_PRINT("CleanUpLock: deleting", proclock);
1508  SHMQueueDelete(&proclock->lockLink);
1509  SHMQueueDelete(&proclock->procLink);
1510  proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
1512  (void *) &(proclock->tag),
1513  proclock_hashcode,
1514  HASH_REMOVE,
1515  NULL))
1516  elog(PANIC, "proclock table corrupted");
1517  }
1518 
1519  if (lock->nRequested == 0)
1520  {
1521  /*
1522  * The caller just released the last lock, so garbage-collect the lock
1523  * object.
1524  */
1525  LOCK_PRINT("CleanUpLock: deleting", lock, 0);
1526  Assert(SHMQueueEmpty(&(lock->procLocks)));
1528  (void *) &(lock->tag),
1529  hashcode,
1530  HASH_REMOVE,
1531  NULL))
1532  elog(PANIC, "lock table corrupted");
1533  }
1534  else if (wakeupNeeded)
1535  {
1536  /* There are waiters on this lock, so wake them up. */
1537  ProcLockWakeup(lockMethodTable, lock);
1538  }
1539 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
PROCLOCKTAG tag
Definition: lock.h:347
int nRequested
Definition: lock.h:295
LOCKMASK holdMask
Definition: lock.h:351
LOCKTAG tag
Definition: lock.h:287
SHM_QUEUE lockLink
Definition: lock.h:353
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:268
SHM_QUEUE procLocks
Definition: lock.h:292
bool SHMQueueEmpty(const SHM_QUEUE *queue)
Definition: shmqueue.c:180
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition: proc.c:1595
SHM_QUEUE procLink
Definition: lock.h:354
#define LOCK_PRINT(where, lock, type)
Definition: lock.c:337
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
static HTAB * LockMethodLockHash
Definition: lock.c:253
void SHMQueueDelete(SHM_QUEUE *queue)
Definition: shmqueue.c:68
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
#define elog
Definition: elog.h:219
bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)

Definition at line 556 of file lock.c.

References LockMethodData::conflictTab, DEFAULT_LOCKMETHOD, and LOCKBIT_ON.

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

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

Definition at line 2644 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, LOCKTAG::locktag_field2, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), LOCALLOCKTAG::mode, PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, NULL, ProcLockHashCode(), SetupLockInTable(), PROCLOCK::tag, and LOCALLOCK::tag.

Referenced by AtPrepare_Locks().

2645 {
2646  LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
2647  LOCKTAG *locktag = &locallock->tag.lock;
2648  PROCLOCK *proclock = NULL;
2649  LWLock *partitionLock = LockHashPartitionLock(locallock->hashcode);
2650  Oid relid = locktag->locktag_field2;
2651  uint32 f;
2652 
2654 
2655  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2656  {
2657  uint32 lockmode;
2658 
2659  /* Look for an allocated slot matching the given relid. */
2660  if (relid != MyProc->fpRelId[f] || FAST_PATH_GET_BITS(MyProc, f) == 0)
2661  continue;
2662 
2663  /* If we don't have a lock of the given mode, forget it! */
2664  lockmode = locallock->tag.mode;
2665  if (!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2666  break;
2667 
2668  /* Find or create lock object. */
2669  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2670 
2671  proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
2672  locallock->hashcode, lockmode);
2673  if (!proclock)
2674  {
2675  LWLockRelease(partitionLock);
2677  ereport(ERROR,
2678  (errcode(ERRCODE_OUT_OF_MEMORY),
2679  errmsg("out of shared memory"),
2680  errhint("You might need to increase max_locks_per_transaction.")));
2681  }
2682  GrantLock(proclock->tag.myLock, proclock, lockmode);
2683  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2684 
2685  LWLockRelease(partitionLock);
2686 
2687  /* No need to examine remaining slots. */
2688  break;
2689  }
2690 
2692 
2693  /* Lock may have already been transferred by some other backend. */
2694  if (proclock == NULL)
2695  {
2696  LOCK *lock;
2697  PROCLOCKTAG proclocktag;
2698  uint32 proclock_hashcode;
2699 
2700  LWLockAcquire(partitionLock, LW_SHARED);
2701 
2703  (void *) locktag,
2704  locallock->hashcode,
2705  HASH_FIND,
2706  NULL);
2707  if (!lock)
2708  elog(ERROR, "failed to re-find shared lock object");
2709 
2710  proclocktag.myLock = lock;
2711  proclocktag.myProc = MyProc;
2712 
2713  proclock_hashcode = ProcLockHashCode(&proclocktag, locallock->hashcode);
2714  proclock = (PROCLOCK *)
2716  (void *) &proclocktag,
2717  proclock_hashcode,
2718  HASH_FIND,
2719  NULL);
2720  if (!proclock)
2721  elog(ERROR, "failed to re-find shared proclock object");
2722  LWLockRelease(partitionLock);
2723  }
2724 
2725  return proclock;
2726 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
PROCLOCKTAG tag
Definition: lock.h:347
uint32 hashcode
Definition: lock.h:409
Definition: lwlock.h:32
LOCALLOCKTAG tag
Definition: lock.h:404
int errhint(const char *fmt,...)
Definition: elog.c:987
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1067
LOCKTAG lock
Definition: lock.h:385
LOCKMODE mode
Definition: lock.h:386
PGPROC * MyProc
Definition: proc.c:67
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1415
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
Definition: lock.h:178
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
int errcode(int sqlerrcode)
Definition: elog.c:575
static HTAB * LockMethodProcLockHash
Definition: lock.c:254
unsigned int Oid
Definition: postgres_ext.h:31
#define DEFAULT_LOCKMETHOD
Definition: lock.h:128
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#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:70
uint32 locktag_field2
Definition: lock.h:181
unsigned int uint32
Definition: c.h:268
Definition: lock.h:284
#define ereport(elevel, rest)
Definition: elog.h:122
#define NULL
Definition: c.h:229
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:179
LWLock backendLock
Definition: proc.h:175
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
PGPROC * myProc
Definition: lock.h:341
Definition: lock.h:344
int errmsg(const char *fmt,...)
Definition: elog.c:797
LOCK * myLock
Definition: lock.h:340
static const LockMethod LockMethods[]
Definition: lock.c:150
#define elog
Definition: elog.h:219
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:186
static bool FastPathGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

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

2490 {
2491  uint32 f;
2492  uint32 unused_slot = FP_LOCK_SLOTS_PER_BACKEND;
2493 
2494  /* Scan for existing entry for this relid, remembering empty slot. */
2495  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2496  {
2497  if (FAST_PATH_GET_BITS(MyProc, f) == 0)
2498  unused_slot = f;
2499  else if (MyProc->fpRelId[f] == relid)
2500  {
2501  Assert(!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode));
2502  FAST_PATH_SET_LOCKMODE(MyProc, f, lockmode);
2503  return true;
2504  }
2505  }
2506 
2507  /* If no existing entry, use any empty slot. */
2508  if (unused_slot < FP_LOCK_SLOTS_PER_BACKEND)
2509  {
2510  MyProc->fpRelId[unused_slot] = relid;
2511  FAST_PATH_SET_LOCKMODE(MyProc, unused_slot, lockmode);
2513  return true;
2514  }
2515 
2516  /* No existing entry, and no empty slot. */
2517  return false;
2518 }
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:70
unsigned int uint32
Definition: c.h:268
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:179
#define Assert(condition)
Definition: c.h:676
static bool FastPathTransferRelationLocks ( LockMethod  lockMethodTable,
const LOCKTAG locktag,
uint32  hashcode 
)
static

Definition at line 2556 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, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PROCLOCKTAG::myLock, ProcGlobal, SetupLockInTable(), and PROCLOCK::tag.

Referenced by LockAcquireExtended().

2558 {
2559  LWLock *partitionLock = LockHashPartitionLock(hashcode);
2560  Oid relid = locktag->locktag_field2;
2561  uint32 i;
2562 
2563  /*
2564  * Every PGPROC that can potentially hold a fast-path lock is present in
2565  * ProcGlobal->allProcs. Prepared transactions are not, but any
2566  * outstanding fast-path locks held by prepared transactions are
2567  * transferred to the main lock table.
2568  */
2569  for (i = 0; i < ProcGlobal->allProcCount; i++)
2570  {
2571  PGPROC *proc = &ProcGlobal->allProcs[i];
2572  uint32 f;
2573 
2575 
2576  /*
2577  * If the target backend isn't referencing the same database as the
2578  * lock, then we needn't examine the individual relation IDs at all;
2579  * none of them can be relevant.
2580  *
2581  * proc->databaseId is set at backend startup time and never changes
2582  * thereafter, so it might be safe to perform this test before
2583  * acquiring &proc->backendLock. In particular, it's certainly safe
2584  * to assume that if the target backend holds any fast-path locks, it
2585  * must have performed a memory-fencing operation (in particular, an
2586  * LWLock acquisition) since setting proc->databaseId. However, it's
2587  * less clear that our backend is certain to have performed a memory
2588  * fencing operation since the other backend set proc->databaseId. So
2589  * for now, we test it after acquiring the LWLock just to be safe.
2590  */
2591  if (proc->databaseId != locktag->locktag_field1)
2592  {
2593  LWLockRelease(&proc->backendLock);
2594  continue;
2595  }
2596 
2597  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2598  {
2599  uint32 lockmode;
2600 
2601  /* Look for an allocated slot matching the given relid. */
2602  if (relid != proc->fpRelId[f] || FAST_PATH_GET_BITS(proc, f) == 0)
2603  continue;
2604 
2605  /* Find or create lock object. */
2606  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2607  for (lockmode = FAST_PATH_LOCKNUMBER_OFFSET;
2609  ++lockmode)
2610  {
2611  PROCLOCK *proclock;
2612 
2613  if (!FAST_PATH_CHECK_LOCKMODE(proc, f, lockmode))
2614  continue;
2615  proclock = SetupLockInTable(lockMethodTable, proc, locktag,
2616  hashcode, lockmode);
2617  if (!proclock)
2618  {
2619  LWLockRelease(partitionLock);
2620  LWLockRelease(&proc->backendLock);
2621  return false;
2622  }
2623  GrantLock(proclock->tag.myLock, proclock, lockmode);
2624  FAST_PATH_CLEAR_LOCKMODE(proc, f, lockmode);
2625  }
2626  LWLockRelease(partitionLock);
2627 
2628  /* No need to examine remaining slots. */
2629  break;
2630  }
2631  LWLockRelease(&proc->backendLock);
2632  }
2633  return true;
2634 }
PROCLOCKTAG tag
Definition: lock.h:347
Definition: lwlock.h:32
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition: lock.c:1067
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition: lock.c:1415
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
PROC_HDR * ProcGlobal
Definition: proc.c:80
unsigned int Oid
Definition: postgres_ext.h:31
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:188
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
uint32 locktag_field2
Definition: lock.h:181
Oid databaseId
Definition: proc.h:113
unsigned int uint32
Definition: c.h:268
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:179
LWLock backendLock
Definition: proc.h:175
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
uint32 allProcCount
Definition: proc.h:236
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition: lock.c:175
Definition: lock.h:344
int i
LOCK * myLock
Definition: lock.h:340
PGPROC * allProcs
Definition: proc.h:232
#define FAST_PATH_BITS_PER_SLOT
Definition: lock.c:174
uint32 locktag_field1
Definition: lock.h:180
Definition: proc.h:94
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:186
static bool FastPathUnGrantRelationLock ( Oid  relid,
LOCKMODE  lockmode 
)
static

Definition at line 2526 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, MyProc, and result.

Referenced by LockRelease(), and LockReleaseAll().

2527 {
2528  uint32 f;
2529  bool result = false;
2530 
2532  for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2533  {
2534  if (MyProc->fpRelId[f] == relid
2535  && FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
2536  {
2537  Assert(!result);
2538  FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2539  result = true;
2540  /* we continue iterating so as to update FastPathLocalUseCount */
2541  }
2542  if (FAST_PATH_GET_BITS(MyProc, f) != 0)
2544  }
2545  return result;
2546 }
PGPROC * MyProc
Definition: proc.c:67
#define FAST_PATH_GET_BITS(proc, n)
Definition: lock.c:177
static int FastPathLocalUseCount
Definition: lock.c:171
return result
Definition: formatting.c:1633
#define FAST_PATH_CHECK_LOCKMODE(proc, n, l)
Definition: lock.c:188
#define FP_LOCK_SLOTS_PER_BACKEND
Definition: proc.h:70
unsigned int uint32
Definition: c.h:268
Oid fpRelId[FP_LOCK_SLOTS_PER_BACKEND]
Definition: proc.h:179
#define Assert(condition)
Definition: c.h:676
#define FAST_PATH_CLEAR_LOCKMODE(proc, n, l)
Definition: lock.c:186
static void FinishStrongLockAcquire ( void  )
static

Definition at line 1604 of file lock.c.

References NULL.

Referenced by LockAcquireExtended().

1605 {
1607 }
static LOCALLOCK * StrongLockInProgress
Definition: lock.c:259
#define NULL
Definition: c.h:229
BlockedProcsData* GetBlockerStatusData ( int  blocked_pid)

Definition at line 3582 of file lock.c.

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

Referenced by pg_blocking_pids().

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

Definition at line 2745 of file lock.c.

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

Referenced by ResolveRecoveryConflictWithLock(), and WaitForLockersMultiple().

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

Definition at line 3845 of file lock.c.

References Assert, lengthof, and LockMethodData::lockModeNames.

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

3846 {
3847  Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
3848  Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
3849  return LockMethods[lockmethodid]->lockModeNames[mode];
3850 }
#define lengthof(array)
Definition: c.h:562
#define Assert(condition)
Definition: c.h:676
static const LockMethod LockMethods[]
Definition: lock.c:150
const char *const * lockModeNames
Definition: lock.h:115
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:562
uint16 LOCKMETHODID
Definition: lock.h:125
#define Assert(condition)
Definition: c.h:676
static const LockMethod LockMethods[]
Definition: lock.c:150
#define LOCK_LOCKMETHOD(lock)
Definition: lock.h:300
LockData* GetLockStatusData ( void  )

Definition at line 3398 of file lock.c.

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

Referenced by pg_lock_status().

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

Definition at line 3762 of file lock.c.

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

Referenced by LogStandbySnapshot().

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

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

3663 {
3664  LOCK *theLock = blocked_proc->waitLock;
3665  BlockedProcData *bproc;
3666  SHM_QUEUE *procLocks;
3667  PROCLOCK *proclock;
3668  PROC_QUEUE *waitQueue;
3669  PGPROC *proc;
3670  int queue_size;
3671  int i;
3672 
3673  /* Nothing to do if this proc is not blocked */
3674  if (theLock == NULL)
3675  return;
3676 
3677  /* Set up a procs[] element */
3678  bproc = &data->procs[data->nprocs++];
3679  bproc->pid = blocked_proc->pid;
3680  bproc->first_lock = data->nlocks;
3681  bproc->first_waiter = data->npids;
3682 
3683  /*
3684  * We may ignore the proc's fast-path arrays, since nothing in those could
3685  * be related to a contended lock.
3686  */
3687 
3688  /* Collect all PROCLOCKs associated with theLock */
3689  procLocks = &(theLock->procLocks);
3690  proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3691  offsetof(PROCLOCK, lockLink));
3692  while (proclock)
3693  {
3694  PGPROC *proc = proclock->tag.myProc;
3695  LOCK *lock = proclock->tag.myLock;
3696  LockInstanceData *instance;
3697 
3698  if (data->nlocks >= data->maxlocks)
3699  {
3700  data->maxlocks += MaxBackends;
3701  data->locks = (LockInstanceData *)
3702  repalloc(data->locks, sizeof(LockInstanceData) * data->maxlocks);
3703  }
3704 
3705  instance = &data->locks[data->nlocks];
3706  memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3707  instance->holdMask = proclock->holdMask;
3708  if (proc->waitLock == lock)
3709  instance->waitLockMode = proc->waitLockMode;
3710  else
3711  instance->waitLockMode = NoLock;
3712  instance->backend = proc->backendId;
3713  instance->lxid = proc->lxid;
3714  instance->pid = proc->pid;
3715  instance->leaderPid = proclock->groupLeader->pid;
3716  instance->fastpath = false;
3717  data->nlocks++;
3718 
3719  proclock = (PROCLOCK *) SHMQueueNext(procLocks, &proclock->lockLink,
3720  offsetof(PROCLOCK, lockLink));
3721  }
3722 
3723  /* Enlarge waiter_pids[] if it's too small to hold all wait queue PIDs */
3724  waitQueue = &(theLock->waitProcs);
3725  queue_size = waitQueue->size;
3726 
3727  if (queue_size > data->maxpids - data->npids)
3728  {
3729  data->maxpids = Max(data->maxpids + MaxBackends,
3730  data->npids + queue_size);
3731  data->waiter_pids = (int *) repalloc(data->waiter_pids,
3732  sizeof(int) * data->maxpids);
3733  }
3734 
3735  /* Collect PIDs from the lock's wait queue, stopping at blocked_proc */
3736  proc = (PGPROC *) waitQueue->links.next;
3737  for (i = 0; i < queue_size; i++)
3738  {
3739  if (proc == blocked_proc)
3740  break;
3741  data->waiter_pids[data->npids++] = proc->pid;
3742  proc = (PGPROC *) proc->links.next;
3743  }
3744 
3745  bproc->num_locks = data->nlocks - bproc->first_lock;
3746  bproc->num_waiters = data->npids - bproc->first_waiter;
3747 }
PROCLOCKTAG tag
Definition: lock.h:347
int * waiter_pids
Definition: lock.h:460
BackendId backendId
Definition: proc.h:112
int first_lock
Definition: lock.h:448
SHM_QUEUE links
Definition: lock.h:32
int num_waiters
Definition: lock.h:453
LOCKMASK holdMask
Definition: lock.h:351
SHM_QUEUE links
Definition: proc.h:97
struct SHM_QUEUE * next
Definition: shmem.h:31
bool fastpath
Definition: lock.h:434
LOCKMODE waitLockMode
Definition: proc.h:137
LOCKTAG tag
Definition: lock.h:287
Definition: lock.h:178
SHM_QUEUE lockLink
Definition: lock.h:353
BlockedProcData * procs
Definition: lock.h:458
LOCKTAG locktag
Definition: lock.h:427
LOCKMODE waitLockMode
Definition: lock.h:429
int num_locks
Definition: lock.h:449
PROC_QUEUE waitProcs
Definition: lock.h:293
int leaderPid
Definition: lock.h:433
int MaxBackends
Definition: globals.c:127
#define NoLock
Definition: lockdefs.h:34
Definition: lock.h:284
LOCK * waitLock
Definition: proc.h:135
int maxlocks
Definition: lock.h:464
SHM_QUEUE procLocks
Definition: lock.h:292
LockInstanceData * locks
Definition: lock.h:459
BackendId backend
Definition: lock.h:430
Pointer SHMQueueNext(const SHM_QUEUE *queue, const SHM_QUEUE *curElem, Size linkOffset)
Definition: shmqueue.c:145
int first_waiter
Definition: lock.h:452
#define Max(x, y)
Definition: c.h:801
LocalTransactionId lxid
Definition: lock.h:431
#define NULL
Definition: c.h:229
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
LOCKMASK holdMask
Definition: lock.h:428
PGPROC * myProc
Definition: lock.h:341
Definition: lock.h:344
int i
int size
Definition: lock.h:33
LOCK * myLock
Definition: lock.h:340
Definition: proc.h:94
int pid
Definition: proc.h:108
#define offsetof(type, field)
Definition: c.h:555
PGPROC * groupLeader
Definition: lock.h:350
LocalTransactionId lxid
Definition: proc.h:105
void GrantAwaitedLock ( void  )

Definition at line 1643 of file lock.c.

References GrantLockLocal().

Referenced by LockErrorCleanup(), and ProcSleep().

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

Definition at line 1415 of file lock.c.

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

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

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

Definition at line 1549 of file lock.c.

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

Referenced by GrantAwaitedLock(), and LockAcquireExtended().

1550 {
1551  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1552  int i;
1553 
1554  Assert(locallock->numLockOwners < locallock->maxLockOwners);
1555  /* Count the total */
1556  locallock->nLocks++;
1557  /* Count the per-owner lock */
1558  for (i = 0; i < locallock->numLockOwners; i++)
1559  {
1560  if (lockOwners[i].owner == owner)
1561  {
1562  lockOwners[i].nLocks++;
1563  return;
1564  }
1565  }
1566  lockOwners[i].owner = owner;
1567  lockOwners[i].nLocks = 1;
1568  locallock->numLockOwners++;
1569  if (owner != NULL)
1570  ResourceOwnerRememberLock(owner, locallock);
1571 }
int numLockOwners
Definition: lock.h:411
int64 nLocks
Definition: lock.h:398
int maxLockOwners
Definition: lock.h:412
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
LOCALLOCKOWNER * lockOwners
Definition: lock.h:414
int64 nLocks
Definition: lock.h:410
int i
struct ResourceOwnerData * owner
Definition: lock.h:397
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:889
void InitLocks ( void  )

Definition at line 377 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 4197 of file lock.c.

References lock_twophase_postcommit().

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

Definition at line 4171 of file lock.c.

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

Referenced by lock_twophase_postabort().

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

Definition at line 3958 of file lock.c.

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

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

Definition at line 4139 of file lock.c.

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

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

Definition at line 701 of file lock.c.

References AbortStrongLockAcquire(), AccessExclusiveLock, Assert, PGPROC::backendLock, BeginStrongLockAcquire(), ConflictsWithRelationFastPath, LockMethodData::conflictTab, FastPathStrongRelationLockData::count, CurrentResourceOwner, EligibleForRelationFastPath, elog, ereport, errcode(), errhint(), errmsg(), ERROR, FALSE, FastPathGrantRelationLock(), FastPathLocalUseCount, FastPathStrongLockHashPartition, FastPathTransferRelationLocks(), FinishStrongLockAcquire(), FP_LOCK_SLOTS_PER_BACKEND, GrantLock(), GrantLockLocal(), HASH_ENTER, HASH_REMOVE, hash_search(), hash_search_with_hash_value(), LOCALLOCK::hashcode, PGPROC::heldLocks, PROCLOCK::holdMask, LOCALLOCK::holdsStrongLockCount, InRecovery, lengthof, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_PRINT, LOCKACQUIRE_ALREADY_HELD, LOCKACQUIRE_NOT_AVAIL, LOCKACQUIRE_OK, LOCKBIT_ON, LockCheckConflicts(), LockHashPartitionLock, PROCLOCK::lockLink, LockMethodData::lockModeNames, LOCALLOCK::lockOwners, 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, NULL, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, ProcLockHashCode(), RecoveryInProgress(), RemoveLocalLock(), repalloc(), LOCK::requested, RowExclusiveLock, SetupLockInTable(), SHMQueueDelete(), status(), STATUS_FOUND, STATUS_OK, PROCLOCK::tag, TopMemoryContext, LOCK::waitMask, WaitOnLock(), and XLogStandbyInfoActive.

Referenced by LockAcquire(), and StandbyAcquireAccessExclusiveLock().

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

Definition at line 1292 of file lock.c.

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

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

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

Definition at line 571 of file lock.c.

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

Referenced by LockHasWaitersRelation().

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

Definition at line 2413 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

Definition at line 2443 of file lock.c.

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

Referenced by LockReassignCurrentOwner().

2444 {
2445  LOCALLOCKOWNER *lockOwners;
2446  int i;
2447  int ic = -1;
2448  int ip = -1;
2449 
2450  /*
2451  * Scan to see if there are any locks belonging to current owner or its
2452  * parent
2453  */
2454  lockOwners = locallock->lockOwners;
2455  for (i = locallock->numLockOwners - 1; i >= 0; i--)
2456  {
2457  if (lockOwners[i].owner == CurrentResourceOwner)
2458  ic = i;
2459  else if (lockOwners[i].owner == parent)
2460  ip = i;
2461  }
2462 
2463  if (ic < 0)
2464  return; /* no current locks */
2465 
2466  if (ip < 0)
2467  {
2468  /* Parent has no slot, so just give it the child's slot */
2469  lockOwners[ic].owner = parent;
2470  ResourceOwnerRememberLock(parent, locallock);
2471  }
2472  else
2473  {
2474  /* Merge child's count with parent's */
2475  lockOwners[ip].nLocks += lockOwners[ic].nLocks;
2476  /* compact out unused slot */
2477  locallock->numLockOwners--;
2478  if (ic < locallock->numLockOwners)
2479  lockOwners[ic] = lockOwners[locallock->numLockOwners];
2480  }
2482 }
int numLockOwners
Definition: lock.h:411
int64 nLocks
Definition: lock.h:398
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:909
LOCALLOCKOWNER * lockOwners
Definition: lock.h:414
int i
struct ResourceOwnerData * owner
Definition: lock.h:397
void ResourceOwnerRememberLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition: resowner.c:889
static void LockRefindAndRelease ( LockMethod  lockMethodTable,
PGPROC proc,
LOCKTAG locktag,
LOCKMODE  lockmode,
bool  decrement_strong_lock_count 
)
static

Definition at line 2962 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, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), FastPathStrongRelationLockData::mutex, PROCLOCKTAG::myLock, PROCLOCKTAG::myProc, NULL, PANIC, PROCLOCK_PRINT, ProcLockHashCode(), SpinLockAcquire, SpinLockRelease, UnGrantLock(), and WARNING.

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

2965 {
2966  LOCK *lock;
2967  PROCLOCK *proclock;
2968  PROCLOCKTAG proclocktag;
2969  uint32 hashcode;
2970  uint32 proclock_hashcode;
2971  LWLock *partitionLock;
2972  bool wakeupNeeded;
2973 
2974  hashcode = LockTagHashCode(locktag);
2975  partitionLock = LockHashPartitionLock(hashcode);
2976 
2977  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2978 
2979  /*
2980  * Re-find the lock object (it had better be there).
2981  */
2983  (void *) locktag,
2984  hashcode,
2985  HASH_FIND,
2986  NULL);
2987  if (!lock)
2988  elog(PANIC, "failed to re-find shared lock object");
2989 
2990  /*
2991  * Re-find the proclock object (ditto).
2992  */
2993  proclocktag.myLock = lock;
2994  proclocktag.myProc = proc;
2995 
2996  proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
2997 
2999  (void *) &proclocktag,
3000  proclock_hashcode,
3001  HASH_FIND,
3002  NULL);
3003  if (!proclock)
3004  elog(PANIC, "failed to re-find shared proclock object");
3005 
3006  /*
3007  * Double-check that we are actually holding a lock of the type we want to
3008  * release.
3009  */
3010  if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
3011  {
3012  PROCLOCK_PRINT("lock_twophase_postcommit: WRONGTYPE", proclock);
3013  LWLockRelease(partitionLock);
3014  elog(WARNING, "you don't own a lock of type %s",
3015  lockMethodTable->lockModeNames[lockmode]);
3016  return;
3017  }
3018 
3019  /*
3020  * Do the releasing. CleanUpLock will waken any now-wakable waiters.
3021  */
3022  wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
3023 
3024  CleanUpLock(lock, proclock,
3025  lockMethodTable, hashcode,
3026  wakeupNeeded);
3027 
3028  LWLockRelease(partitionLock);
3029 
3030  /*
3031  * Decrement strong lock count. This logic is needed only for 2PC.
3032  */
3033  if (decrement_strong_lock_count
3034  && ConflictsWithRelationFastPath(locktag, lockmode))
3035  {
3036  uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
3037 
3039  Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
3040  FastPathStrongRelationLocks->count[fasthashcode]--;
3042  }
3043 }
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:915
Definition: lwlock.h:32
#define ConflictsWithRelationFastPath(locktag, mode)
Definition: lock.c:205
LOCKMASK holdMask
Definition: lock.h:351
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition: lock.c:241
#define LockHashPartitionLock(hashcode)
Definition: lock.h:497
#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:1715
#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:268
Definition: lock.h:284
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition: lock.c:490
#define WARNING
Definition: elog.h:40
#define SpinLockRelease(lock)
Definition: spin.h:64
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
static HTAB * LockMethodLockHash
Definition: lock.c:253
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
PGPROC * myProc
Definition: lock.h:341
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
Definition: lock.h:344
LOCK * myLock
Definition: lock.h:340
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition: lock.c:1438
#define PROCLOCK_PRINT(where, proclockP)
Definition: lock.c:338
#define elog
Definition: elog.h:219
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition: lock.c:1495
const char *const * lockModeNames
Definition: lock.h:115
bool LockRelease ( const LOCKTAG locktag,
LOCKMODE  lockmode,
bool  sessionLock 
)

Definition at line 1818 of file lock.c.

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

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

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

Definition at line 2014 of file lock.c.

References Assert, PGPROC::backendLock, CleanUpLock(), DEFAULT_LOCKMETHOD, EligibleForRelationFastPath, elog, ERROR, FastPathUnGrantRelationLock(), LOCK::grantMask, hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, i, lengthof, LOCALLOCK_LOCKMETHOD, LOCALLOCKTAG::lock, LOCALLOCK::lock, LOCK_LOCKMETHOD, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLockByIndex, 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, NULL, NUM_LOCK_PARTITIONS, LockMethodData::numLockModes, LOCALLOCK::numLockOwners, offsetof, LOCALLOCKOWNER::owner, PANIC, PROCLOCK::procLink, LOCALLOCK::proclock, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), ResourceOwnerForgetLock(), SHMQueueNext(), status(), LOCK::tag, PROCLOCK::tag, LOCALLOCK::tag, LockMethodData::trace_flag, UnGrantLock(), and VirtualXactLockTableCleanup().

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

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

Definition at line 2318 of file lock.c.

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

Referenced by ResourceOwnerReleaseInternal().

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

Definition at line 2288 of file lock.c.

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

Referenced by pg_advisory_unlock_all().

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

Definition at line 3361 of file lock.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

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

Definition at line 490 of file lock.c.

References get_hash_value().

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

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

Definition at line 4387 of file lock.c.

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

Referenced by RelationExtensionLockWaiterCount().

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

Definition at line 3169 of file lock.c.

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

Referenced by PrepareTransaction().

3170 {
3171  PGPROC *newproc = TwoPhaseGetDummyProc(xid);
3173  LOCALLOCK *locallock;
3174  LOCK *lock;
3175  PROCLOCK *proclock;
3176  PROCLOCKTAG proclocktag;
3177  int partition;
3178 
3179  /* Can't prepare a lock group follower. */
3182 
3183  /* This is a critical section: any error means big trouble */
3185 
3186  /*
3187  * First we run through the locallock table and get rid of unwanted
3188  * entries, then we scan the process's proclocks and transfer them to the
3189  * target proc.
3190  *
3191  * We do this separately because we may have multiple locallock entries
3192  * pointing to the same proclock, and we daren't end up with any dangling
3193  * pointers.
3194  */
3196 
3197  while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3198  {
3199  LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3200  bool haveSessionLock;
3201  bool haveXactLock;
3202  int i;
3203 
3204  if (locallock->proclock == NULL || locallock->lock == NULL)
3205  {
3206  /*
3207  * We must've run out of shared memory while trying to set up this
3208  * lock. Just forget the local entry.
3209  */
3210  Assert(locallock->nLocks == 0);
3211  RemoveLocalLock(locallock);
3212  continue;
3213  }
3214 
3215  /* Ignore VXID locks */
3216  if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3217  continue;
3218 
3219  /* Scan to see whether we hold it at session or transaction level */
3220  haveSessionLock = haveXactLock = false;
3221  for (i = locallock->numLockOwners - 1; i >= 0; i--)
3222  {
3223  if (lockOwners[i].owner == NULL)
3224  haveSessionLock = true;
3225  else
3226  haveXactLock = true;
3227  }
3228 
3229  /* Ignore it if we have only session lock */
3230  if (!haveXactLock)
3231  continue;
3232 
3233  /* This can't happen, because we already checked it */
3234  if (haveSessionLock)
3235  ereport(PANIC,
3236  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3237  errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3238 
3239  /* Mark the proclock to show we need to release this lockmode */
3240  if (locallock->nLocks > 0)
3241  locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3242 
3243  /* And remove the locallock hashtable entry */
3244  RemoveLocalLock(locallock);
3245  }
3246 
3247  /*
3248  * Now, scan each lock partition separately.
3249  */
3250  for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3251  {
3252  LWLock *partitionLock;
3253  SHM_QUEUE *procLocks = &(MyProc->myProcLocks[partition]);
3254  PROCLOCK *nextplock;
3255 
3256  partitionLock = LockHashPartitionLockByIndex(partition);
3257 
3258  /*
3259  * If the proclock list for this partition is empty, we can skip
3260  * acquiring the partition lock. This optimization is safer than the
3261  * situation in LockReleaseAll, because we got rid of any fast-path
3262  * locks during AtPrepare_Locks, so there cannot be any case where
3263  * another backend is adding something to our lists now. For safety,
3264  * though, we code this the same way as in LockReleaseAll.
3265  */
3266  if (SHMQueueNext(procLocks, procLocks,
3267  offsetof(PROCLOCK, procLink)) == NULL)
3268  continue; /* needn't examine this partition */
3269 
3270  LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3271 
3272  for (proclock = (PROCLOCK *) SHMQueueNext(procLocks, procLocks,
3273  offsetof(PROCLOCK, procLink));
3274  proclock;
3275  proclock = nextplock)
3276  {
3277  /* Get link first, since we may unlink/relink this proclock */
3278  nextplock = (PROCLOCK *)
3279  SHMQueueNext(procLocks, &proclock->procLink,
3280  offsetof(PROCLOCK, procLink));
3281 
3282  Assert(proclock->tag.myProc == MyProc);
3283 
3284  lock = proclock->tag.myLock;
3285 
3286  /* Ignore VXID locks */
3288  continue;
3289 
3290  PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3291  LOCK_PRINT("PostPrepare_Locks", lock, 0);
3292  Assert(lock->nRequested >= 0);
3293  Assert(lock->nGranted >= 0);
3294  Assert(lock->nGranted <= lock->nRequested);
3295  Assert((proclock->holdMask & ~lock->grantMask) == 0);
3296 
3297  /* Ignore it if nothing to release (must be a session lock) */
3298  if (proclock->releaseMask == 0)
3299  continue;
3300 
3301  /* Else we should be releasing all locks */
3302  if (proclock->releaseMask != proclock->holdMask)
3303  elog(PANIC, "we seem to have dropped a bit somewhere");
3304 
3305  /*
3306  * We cannot simply modify proclock->tag.myProc to reassign
3307  * ownership of the lock, because that's part of the hash key and
3308  * the proclock would then be in the wrong hash chain. Instead
3309  * use hash_update_hash_key. (We used to create a new hash entry,
3310  * but that risks out-of-memory failure if other processes are
3311  * busy making proclocks too.) We must unlink the proclock from
3312  * our procLink chain and put it into the new proc's chain, too.
3313  *
3314  * Note: the updated proclock hash key will still belong to the
3315  * same hash partition, cf proclock_hash(). So the partition lock
3316  * we already hold is sufficient for this.
3317  */
3318  SHMQueueDelete(&proclock->procLink);
3319 
3320  /*
3321  * Create the new hash key for the proclock.
3322  */
3323  proclocktag.myLock = lock;
3324  proclocktag.myProc = newproc;
3325 
3326  /*
3327  * Update groupLeader pointer to point to the new proc. (We'd
3328  * better not be a member of somebody else's lock group!)
3329  */
3330  Assert(proclock->groupLeader == proclock->tag.myProc);
3331  proclock->groupLeader = newproc;
3332 
3333  /*
3334  * Update the proclock. We should not find any existing entry for
3335  * the same hash key, since there can be only one entry for any
3336  * given lock with my own proc.
3337  */
3338