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

Go to the source code of this file.

Data Structures

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

Macros

#define InvalidLocalTransactionId   0
 
#define LocalTransactionIdIsValid(lxid)   ((lxid) != InvalidLocalTransactionId)
 
#define VirtualTransactionIdIsValid(vxid)    (LocalTransactionIdIsValid((vxid).localTransactionId))
 
#define VirtualTransactionIdIsRecoveredPreparedXact(vxid)    ((vxid).procNumber == INVALID_PROC_NUMBER)
 
#define VirtualTransactionIdEquals(vxid1, vxid2)
 
#define SetInvalidVirtualTransactionId(vxid)
 
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
 
#define MAX_LOCKMODES   10
 
#define LOCKBIT_ON(lockmode)   (1 << (lockmode))
 
#define LOCKBIT_OFF(lockmode)   (~(1 << (lockmode)))
 
#define LOCK_LOCKMETHOD(lock)   ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
 
#define LOCK_LOCKTAG(lock)   ((LockTagType) (lock).tag.locktag_type)
 
#define PROCLOCK_LOCKMETHOD(proclock)    LOCK_LOCKMETHOD(*((proclock).tag.myLock))
 
#define LOCALLOCK_LOCKMETHOD(llock)   ((llock).tag.lock.locktag_lockmethodid)
 
#define LOCALLOCK_LOCKTAG(llock)   ((LockTagType) (llock).tag.lock.locktag_type)
 
#define LockHashPartition(hashcode)    ((hashcode) % NUM_LOCK_PARTITIONS)
 
#define LockHashPartitionLock(hashcode)
 
#define LockHashPartitionLockByIndex(i)    (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
 
#define LockHashPartitionLockByProc(leader_pgproc)    LockHashPartitionLock(GetNumberFromPGProc(leader_pgproc))
 

Typedefs

typedef struct PGPROC PGPROC
 
typedef struct VirtualTransactionId VirtualTransactionId
 
typedef struct LockMethodData LockMethodData
 
typedef const LockMethodDataLockMethod
 
typedef struct LOCK LOCK
 
typedef struct PROCLOCKTAG PROCLOCKTAG
 
typedef struct PROCLOCK PROCLOCK
 
typedef struct LOCALLOCKTAG LOCALLOCKTAG
 
typedef struct LOCALLOCKOWNER LOCALLOCKOWNER
 
typedef struct LOCALLOCK LOCALLOCK
 
typedef struct LockInstanceData LockInstanceData
 
typedef struct LockData LockData
 
typedef struct BlockedProcData BlockedProcData
 
typedef struct BlockedProcsData BlockedProcsData
 

Enumerations

enum  LockAcquireResult { LOCKACQUIRE_NOT_AVAIL , LOCKACQUIRE_OK , LOCKACQUIRE_ALREADY_HELD , LOCKACQUIRE_ALREADY_CLEAR }
 
enum  DeadLockState {
  DS_NOT_YET_CHECKED , DS_NO_DEADLOCK , DS_SOFT_DEADLOCK , DS_HARD_DEADLOCK ,
  DS_BLOCKED_BY_AUTOVACUUM
}
 

Functions

void InitLockManagerAccess (void)
 
LockMethod GetLocksMethodTable (const LOCK *lock)
 
LockMethod GetLockTagsMethodTable (const LOCKTAG *locktag)
 
uint32 LockTagHashCode (const LOCKTAG *locktag)
 
bool DoLockModesConflict (LOCKMODE mode1, LOCKMODE mode2)
 
LockAcquireResult LockAcquire (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
 
LockAcquireResult LockAcquireExtended (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
 
void AbortStrongLockAcquire (void)
 
void MarkLockClear (LOCALLOCK *locallock)
 
bool LockRelease (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
void LockReleaseAll (LOCKMETHODID lockmethodid, bool allLocks)
 
void LockReleaseSession (LOCKMETHODID lockmethodid)
 
void LockReleaseCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
void LockReassignCurrentOwner (LOCALLOCK **locallocks, int nlocks)
 
bool LockHeldByMe (const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
 
bool LockHasWaiters (const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
 
VirtualTransactionIdGetLockConflicts (const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
 
void AtPrepare_Locks (void)
 
void PostPrepare_Locks (FullTransactionId fxid)
 
bool LockCheckConflicts (LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
 
void GrantLock (LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
 
void GrantAwaitedLock (void)
 
LOCALLOCKGetAwaitedLock (void)
 
void ResetAwaitedLock (void)
 
void RemoveFromWaitQueue (PGPROC *proc, uint32 hashcode)
 
LockDataGetLockStatusData (void)
 
BlockedProcsDataGetBlockerStatusData (int blocked_pid)
 
xl_standby_lockGetRunningTransactionLocks (int *nlocks)
 
const charGetLockmodeName (LOCKMETHODID lockmethodid, LOCKMODE mode)
 
void lock_twophase_recover (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_postcommit (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_postabort (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
void lock_twophase_standby_recover (FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
 
DeadLockState DeadLockCheck (PGPROC *proc)
 
PGPROCGetBlockingAutoVacuumPgproc (void)
 
pg_noreturn void DeadLockReport (void)
 
void RememberSimpleDeadLock (PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
 
void InitDeadLockChecking (void)
 
int LockWaiterCount (const LOCKTAG *locktag)
 
void VirtualXactLockTableInsert (VirtualTransactionId vxid)
 
void VirtualXactLockTableCleanup (void)
 
bool VirtualXactLock (VirtualTransactionId vxid, bool wait)
 

Variables

PGDLLIMPORT int max_locks_per_xact
 
PGDLLIMPORT bool log_lock_failures
 

Macro Definition Documentation

◆ GET_VXID_FROM_PGPROC

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

Definition at line 80 of file lock.h.

111{
112 int numLockModes;
113 const LOCKMASK *conflictTab;
114 const char *const *lockModeNames;
115 const bool *trace_flag;
117
118typedef const LockMethodData *LockMethod;
119
120/*
121 * Per-locked-object lock information:
122 *
123 * tag -- uniquely identifies the object being locked
124 * grantMask -- bitmask for all lock types currently granted on this object.
125 * waitMask -- bitmask for all lock types currently awaited on this object.
126 * procLocks -- list of PROCLOCK objects for this lock.
127 * waitProcs -- queue of processes waiting for this lock.
128 * requested -- count of each lock type currently requested on the lock
129 * (includes requests already granted!!).
130 * nRequested -- total requested locks of all types.
131 * granted -- count of each lock type currently granted on the lock.
132 * nGranted -- total granted locks of all types.
133 *
134 * Note: these counts count 1 for each backend. Internally to a backend,
135 * there may be multiple grabs on a particular lock, but this is not reflected
136 * into shared memory.
137 */
138typedef struct LOCK
139{
140 /* hash key */
141 LOCKTAG tag; /* unique identifier of lockable object */
142
143 /* data */
144 LOCKMASK grantMask; /* bitmask for lock types already granted */
145 LOCKMASK waitMask; /* bitmask for lock types awaited */
146 dlist_head procLocks; /* list of PROCLOCK objects assoc. with lock */
147 dclist_head waitProcs; /* list of PGPROC objects waiting on lock */
148 int requested[MAX_LOCKMODES]; /* counts of requested locks */
149 int nRequested; /* total of requested[] array */
150 int granted[MAX_LOCKMODES]; /* counts of granted locks */
151 int nGranted; /* total of granted[] array */
152} LOCK;
153
154#define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
155#define LOCK_LOCKTAG(lock) ((LockTagType) (lock).tag.locktag_type)
156
157
158/*
159 * We may have several different backends holding or awaiting locks
160 * on the same lockable object. We need to store some per-holder/waiter
161 * information for each such holder (or would-be holder). This is kept in
162 * a PROCLOCK struct.
163 *
164 * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the
165 * proclock hashtable. A PROCLOCKTAG value uniquely identifies the combination
166 * of a lockable object and a holder/waiter for that object. (We can use
167 * pointers here because the PROCLOCKTAG need only be unique for the lifespan
168 * of the PROCLOCK, and it will never outlive the lock or the proc.)
169 *
170 * Internally to a backend, it is possible for the same lock to be held
171 * for different purposes: the backend tracks transaction locks separately
172 * from session locks. However, this is not reflected in the shared-memory
173 * state: we only track which backend(s) hold the lock. This is OK since a
174 * backend can never block itself.
175 *
176 * The holdMask field shows the already-granted locks represented by this
177 * proclock. Note that there will be a proclock object, possibly with
178 * zero holdMask, for any lock that the process is currently waiting on.
179 * Otherwise, proclock objects whose holdMasks are zero are recycled
180 * as soon as convenient.
181 *
182 * releaseMask is workspace for LockReleaseAll(): it shows the locks due
183 * to be released during the current call. This must only be examined or
184 * set by the backend owning the PROCLOCK.
185 *
186 * Each PROCLOCK object is linked into lists for both the associated LOCK
187 * object and the owning PGPROC object. Note that the PROCLOCK is entered
188 * into these lists as soon as it is created, even if no lock has yet been
189 * granted. A PGPROC that is waiting for a lock to be granted will also be
190 * linked into the lock's waitProcs queue.
191 */
192typedef struct PROCLOCKTAG
193{
194 /* NB: we assume this struct contains no padding! */
195 LOCK *myLock; /* link to per-lockable-object information */
196 PGPROC *myProc; /* link to PGPROC of owning backend */
198
199typedef struct PROCLOCK
200{
201 /* tag */
202 PROCLOCKTAG tag; /* unique identifier of proclock object */
203
204 /* data */
205 PGPROC *groupLeader; /* proc's lock group leader, or proc itself */
206 LOCKMASK holdMask; /* bitmask for lock types currently held */
207 LOCKMASK releaseMask; /* bitmask for lock types to be released */
208 dlist_node lockLink; /* list link in LOCK's list of proclocks */
209 dlist_node procLink; /* list link in PGPROC's list of proclocks */
210} PROCLOCK;
211
212#define PROCLOCK_LOCKMETHOD(proclock) \
213 LOCK_LOCKMETHOD(*((proclock).tag.myLock))
214
215/*
216 * Each backend also maintains a local hash table with information about each
217 * lock it is currently interested in. In particular the local table counts
218 * the number of times that lock has been acquired. This allows multiple
219 * requests for the same lock to be executed without additional accesses to
220 * shared memory. We also track the number of lock acquisitions per
221 * ResourceOwner, so that we can release just those locks belonging to a
222 * particular ResourceOwner.
223 *
224 * When holding a lock taken "normally", the lock and proclock fields always
225 * point to the associated objects in shared memory. However, if we acquired
226 * the lock via the fast-path mechanism, the lock and proclock fields are set
227 * to NULL, since there probably aren't any such objects in shared memory.
228 * (If the lock later gets promoted to normal representation, we may eventually
229 * update our locallock's lock/proclock fields after finding the shared
230 * objects.)
231 *
232 * Caution: a locallock object can be left over from a failed lock acquisition
233 * attempt. In this case its lock/proclock fields are untrustworthy, since
234 * the shared lock object is neither held nor awaited, and hence is available
235 * to be reclaimed. If nLocks > 0 then these pointers must either be valid or
236 * NULL, but when nLocks == 0 they should be considered garbage.
237 */
238typedef struct LOCALLOCKTAG
239{
240 LOCKTAG lock; /* identifies the lockable object */
241 LOCKMODE mode; /* lock mode for this table entry */
243
244typedef struct LOCALLOCKOWNER
245{
246 /*
247 * Note: if owner is NULL then the lock is held on behalf of the session;
248 * otherwise it is held on behalf of my current transaction.
249 *
250 * Must use a forward struct reference to avoid circularity.
251 */
252 struct ResourceOwnerData *owner;
253 int64 nLocks; /* # of times held by this owner */
255
256typedef struct LOCALLOCK
257{
258 /* tag */
259 LOCALLOCKTAG tag; /* unique identifier of locallock entry */
260
261 /* data */
262 uint32 hashcode; /* copy of LOCKTAG's hash value */
263 LOCK *lock; /* associated LOCK object, if any */
264 PROCLOCK *proclock; /* associated PROCLOCK object, if any */
265 int64 nLocks; /* total number of times lock is held */
266 int numLockOwners; /* # of relevant ResourceOwners */
267 int maxLockOwners; /* allocated size of array */
268 LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */
269 bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */
270 bool lockCleared; /* we read all sinval msgs for lock */
271} LOCALLOCK;
272
273#define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid)
274#define LOCALLOCK_LOCKTAG(llock) ((LockTagType) (llock).tag.lock.locktag_type)
275
276
277/*
278 * These structures hold information passed from lmgr internals to the lock
279 * listing user-level functions (in lockfuncs.c).
280 */
281
282typedef struct LockInstanceData
283{
284 LOCKTAG locktag; /* tag for locked object */
285 LOCKMASK holdMask; /* locks held by this PGPROC */
286 LOCKMODE waitLockMode; /* lock awaited by this PGPROC, if any */
287 VirtualTransactionId vxid; /* virtual transaction ID of this PGPROC */
288 TimestampTz waitStart; /* time at which this PGPROC started waiting
289 * for lock */
290 int pid; /* pid of this PGPROC */
291 int leaderPid; /* pid of group leader; = pid if no group */
292 bool fastpath; /* taken via fastpath? */
294
295typedef struct LockData
296{
297 int nelements; /* The length of the array */
298 LockInstanceData *locks; /* Array of per-PROCLOCK information */
299} LockData;
300
301typedef struct BlockedProcData
302{
303 int pid; /* pid of a blocked PGPROC */
304 /* Per-PROCLOCK information about PROCLOCKs of the lock the pid awaits */
305 /* (these fields refer to indexes in BlockedProcsData.locks[]) */
306 int first_lock; /* index of first relevant LockInstanceData */
307 int num_locks; /* number of relevant LockInstanceDatas */
308 /* PIDs of PGPROCs that are ahead of "pid" in the lock's wait queue */
309 /* (these fields refer to indexes in BlockedProcsData.waiter_pids[]) */
310 int first_waiter; /* index of first preceding waiter */
311 int num_waiters; /* number of preceding waiters */
313
314typedef struct BlockedProcsData
315{
316 BlockedProcData *procs; /* Array of per-blocked-proc information */
317 LockInstanceData *locks; /* Array of per-PROCLOCK information */
318 int *waiter_pids; /* Array of PIDs of other blocked PGPROCs */
319 int nprocs; /* # of valid entries in procs[] array */
320 int maxprocs; /* Allocated length of procs[] array */
321 int nlocks; /* # of valid entries in locks[] array */
322 int maxlocks; /* Allocated length of locks[] array */
323 int npids; /* # of valid entries in waiter_pids[] array */
324 int maxpids; /* Allocated length of waiter_pids[] array */
326
327
328/* Result codes for LockAcquire() */
329typedef enum
330{
331 LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
332 LOCKACQUIRE_OK, /* lock successfully acquired */
333 LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
334 LOCKACQUIRE_ALREADY_CLEAR, /* incremented count for lock already clear */
336
337/* Deadlock states identified by DeadLockCheck() */
338typedef enum
339{
340 DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
341 DS_NO_DEADLOCK, /* no deadlock detected */
342 DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
343 DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
344 DS_BLOCKED_BY_AUTOVACUUM, /* no deadlock; queue blocked by autovacuum
345 * worker */
347
348/*
349 * The lockmgr's shared hash tables are partitioned to reduce contention.
350 * To determine which partition a given locktag belongs to, compute the tag's
351 * hash code with LockTagHashCode(), then apply one of these macros.
352 * NB: NUM_LOCK_PARTITIONS must be a power of 2!
353 */
354#define LockHashPartition(hashcode) \
355 ((hashcode) % NUM_LOCK_PARTITIONS)
356#define LockHashPartitionLock(hashcode) \
357 (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + \
358 LockHashPartition(hashcode)].lock)
359#define LockHashPartitionLockByIndex(i) \
360 (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
361
362/*
363 * The deadlock detector needs to be able to access lockGroupLeader and
364 * related fields in the PGPROC, so we arrange for those fields to be protected
365 * by one of the lock hash partition locks. Since the deadlock detector
366 * acquires all such locks anyway, this makes it safe for it to access these
367 * fields without doing anything extra. To avoid contention as much as
368 * possible, we map different PGPROCs to different partition locks. The lock
369 * used for a given lock group is determined by the group leader's pgprocno.
370 */
371#define LockHashPartitionLockByProc(leader_pgproc) \
372 LockHashPartitionLock(GetNumberFromPGProc(leader_pgproc))
373
374/*
375 * function prototypes
376 */
377extern void InitLockManagerAccess(void);
378extern LockMethod GetLocksMethodTable(const LOCK *lock);
379extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag);
380extern uint32 LockTagHashCode(const LOCKTAG *locktag);
382extern LockAcquireResult LockAcquire(const LOCKTAG *locktag,
383 LOCKMODE lockmode,
384 bool sessionLock,
385 bool dontWait);
386extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag,
387 LOCKMODE lockmode,
388 bool sessionLock,
389 bool dontWait,
392 bool logLockFailure);
393extern void AbortStrongLockAcquire(void);
394extern void MarkLockClear(LOCALLOCK *locallock);
395extern bool LockRelease(const LOCKTAG *locktag,
396 LOCKMODE lockmode, bool sessionLock);
399extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks);
400extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks);
401extern bool LockHeldByMe(const LOCKTAG *locktag,
402 LOCKMODE lockmode, bool orstronger);
403#ifdef USE_ASSERT_CHECKING
404extern HTAB *GetLockMethodLocalHash(void);
405#endif
406extern bool LockHasWaiters(const LOCKTAG *locktag,
407 LOCKMODE lockmode, bool sessionLock);
408extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
409 LOCKMODE lockmode, int *countp);
410extern void AtPrepare_Locks(void);
411extern void PostPrepare_Locks(FullTransactionId fxid);
413 LOCKMODE lockmode,
414 LOCK *lock, PROCLOCK *proclock);
415extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
416extern void GrantAwaitedLock(void);
417extern LOCALLOCK *GetAwaitedLock(void);
418extern void ResetAwaitedLock(void);
419
420extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode);
421extern LockData *GetLockStatusData(void);
423
426
427extern void lock_twophase_recover(FullTransactionId fxid, uint16 info,
428 void *recdata, uint32 len);
430 void *recdata, uint32 len);
432 void *recdata, uint32 len);
434 void *recdata, uint32 len);
435
438pg_noreturn extern void DeadLockReport(void);
440 LOCKMODE lockmode,
441 LOCK *lock,
442 PGPROC *proc2);
443extern void InitDeadLockChecking(void);
444
445extern int LockWaiterCount(const LOCKTAG *locktag);
446
447#ifdef LOCK_DEBUG
448extern void DumpLocks(PGPROC *proc);
449extern void DumpAllLocks(void);
450#endif
451
452/* Lock a VXID (used to wait for a transaction to finish) */
454extern void VirtualXactLockTableCleanup(void);
455extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait);
456
457#endif /* LOCK_H_ */
#define pg_noreturn
Definition c.h:190
int64_t int64
Definition c.h:621
uint16_t uint16
Definition c.h:623
uint32_t uint32
Definition c.h:624
int64 TimestampTz
Definition timestamp.h:39
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition lock.c:807
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition lock.c:641
void lock_twophase_postabort(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4579
void PostPrepare_Locks(FullTransactionId fxid)
Definition lock.c:3581
void lock_twophase_standby_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4521
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
Definition lock.c:621
const LockMethodData * LockMethod
Definition lock.h:119
void VirtualXactLockTableInsert(VirtualTransactionId vxid)
Definition lock.c:4603
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
void GrantAwaitedLock(void)
Definition lock.c:1898
int LockWaiterCount(const LOCKTAG *locktag)
Definition lock.c:4837
void AtPrepare_Locks(void)
Definition lock.c:3485
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:2111
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition deadlock.c:1147
void InitLockManagerAccess(void)
Definition lock.c:503
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1667
void VirtualXactLockTableCleanup(void)
Definition lock.c:4626
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition lock.c:4726
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition lock.c:3078
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition lock.c:2055
LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
Definition lock.c:834
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition lock.c:2316
void ResetAwaitedLock(void)
Definition lock.c:1916
void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition lock.c:2715
void AbortStrongLockAcquire(void)
Definition lock.c:1869
DeadLockState
Definition lock.h:340
@ DS_HARD_DEADLOCK
Definition lock.h:344
@ DS_BLOCKED_BY_AUTOVACUUM
Definition lock.h:345
@ DS_NO_DEADLOCK
Definition lock.h:342
@ DS_NOT_YET_CHECKED
Definition lock.h:341
@ DS_SOFT_DEADLOCK
Definition lock.h:343
BlockedProcsData * GetBlockerStatusData(int blocked_pid)
Definition lock.c:3980
#define MAX_LOCKMODES
Definition lock.h:85
bool LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:694
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4236
void lock_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4553
void InitDeadLockChecking(void)
Definition deadlock.c:143
void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition lock.c:2620
LOCALLOCK * GetAwaitedLock(void)
Definition lock.c:1907
void LockReleaseSession(LOCKMETHODID lockmethodid)
Definition lock.c:2590
void MarkLockClear(LOCALLOCK *locallock)
Definition lock.c:1929
LockData * GetLockStatusData(void)
Definition lock.c:3777
DeadLockState DeadLockCheck(PGPROC *proc)
Definition deadlock.c:220
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:555
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition lock.c:1538
void lock_twophase_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4340
pg_noreturn void DeadLockReport(void)
Definition deadlock.c:1075
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition lock.c:525
LockAcquireResult
Definition lock.h:331
@ LOCKACQUIRE_ALREADY_CLEAR
Definition lock.h:335
@ LOCKACQUIRE_OK
Definition lock.h:333
@ LOCKACQUIRE_ALREADY_HELD
Definition lock.h:334
@ LOCKACQUIRE_NOT_AVAIL
Definition lock.h:332
xl_standby_lock * GetRunningTransactionLocks(int *nlocks)
Definition lock.c:4154
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
Definition lock.c:537
int LOCKMODE
Definition lockdefs.h:26
int LOCKMASK
Definition lockdefs.h:25
uint16 LOCKMETHODID
Definition locktag.h:22
static PgChecksumMode mode
const void size_t len
int first_lock
Definition lock.h:307
int first_waiter
Definition lock.h:311
int num_waiters
Definition lock.h:312
int num_locks
Definition lock.h:308
LockInstanceData * locks
Definition lock.h:318
int * waiter_pids
Definition lock.h:319
BlockedProcData * procs
Definition lock.h:317
int64 nLocks
Definition lock.h:254
struct ResourceOwnerData * owner
Definition lock.h:253
LOCKTAG lock
Definition lock.h:241
LOCKMODE mode
Definition lock.h:242
LOCALLOCKOWNER * lockOwners
Definition lock.h:269
uint32 hashcode
Definition lock.h:263
int maxLockOwners
Definition lock.h:268
LOCK * lock
Definition lock.h:264
int64 nLocks
Definition lock.h:266
int numLockOwners
Definition lock.h:267
bool holdsStrongLockCount
Definition lock.h:270
PROCLOCK * proclock
Definition lock.h:265
LOCALLOCKTAG tag
Definition lock.h:260
bool lockCleared
Definition lock.h:271
Definition lock.h:140
int nRequested
Definition lock.h:150
LOCKTAG tag
Definition lock.h:142
int requested[MAX_LOCKMODES]
Definition lock.h:149
dclist_head waitProcs
Definition lock.h:148
int granted[MAX_LOCKMODES]
Definition lock.h:151
LOCKMASK grantMask
Definition lock.h:145
LOCKMASK waitMask
Definition lock.h:146
int nGranted
Definition lock.h:152
dlist_head procLocks
Definition lock.h:147
LockInstanceData * locks
Definition lock.h:299
int nelements
Definition lock.h:298
LOCKMASK holdMask
Definition lock.h:286
LOCKMODE waitLockMode
Definition lock.h:287
bool fastpath
Definition lock.h:293
LOCKTAG locktag
Definition lock.h:285
TimestampTz waitStart
Definition lock.h:289
VirtualTransactionId vxid
Definition lock.h:288
Definition proc.h:179
LOCK * myLock
Definition lock.h:196
PGPROC * myProc
Definition lock.h:197
LOCKMASK holdMask
Definition lock.h:207
dlist_node lockLink
Definition lock.h:209
PGPROC * groupLeader
Definition lock.h:206
LOCKMASK releaseMask
Definition lock.h:208
PROCLOCKTAG tag
Definition lock.h:203
dlist_node procLink
Definition lock.h:210

◆ InvalidLocalTransactionId

#define InvalidLocalTransactionId   0

Definition at line 68 of file lock.h.

◆ LOCALLOCK_LOCKMETHOD

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

Definition at line 274 of file lock.h.

◆ LOCALLOCK_LOCKTAG

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

Definition at line 275 of file lock.h.

◆ LocalTransactionIdIsValid

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

Definition at line 69 of file lock.h.

◆ LOCK_LOCKMETHOD

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

Definition at line 155 of file lock.h.

◆ LOCK_LOCKTAG

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

Definition at line 156 of file lock.h.

◆ LOCKBIT_OFF

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

Definition at line 88 of file lock.h.

◆ LOCKBIT_ON

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

Definition at line 87 of file lock.h.

◆ LockHashPartition

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

Definition at line 355 of file lock.h.

◆ LockHashPartitionLock

#define LockHashPartitionLock (   hashcode)
Value:
LWLockPadded * MainLWLockArray
Definition lwlock.c:150
#define LOCK_MANAGER_LWLOCK_OFFSET
Definition lwlock.h:95
LWLock lock
Definition lwlock.h:70

Definition at line 357 of file lock.h.

◆ LockHashPartitionLockByIndex

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

Definition at line 360 of file lock.h.

◆ LockHashPartitionLockByProc

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

Definition at line 372 of file lock.h.

◆ MAX_LOCKMODES

#define MAX_LOCKMODES   10

Definition at line 85 of file lock.h.

◆ PROCLOCK_LOCKMETHOD

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

Definition at line 213 of file lock.h.

◆ SetInvalidVirtualTransactionId

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

Definition at line 77 of file lock.h.

◆ VirtualTransactionIdEquals

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

Definition at line 74 of file lock.h.

◆ VirtualTransactionIdIsRecoveredPreparedXact

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

Definition at line 72 of file lock.h.

◆ VirtualTransactionIdIsValid

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

Definition at line 70 of file lock.h.

Typedef Documentation

◆ BlockedProcData

◆ BlockedProcsData

◆ LOCALLOCK

◆ LOCALLOCKOWNER

◆ LOCALLOCKTAG

◆ LOCK

typedef struct LOCK LOCK

◆ LockData

◆ LockInstanceData

◆ LockMethod

Definition at line 119 of file lock.h.

◆ LockMethodData

◆ PGPROC

Definition at line 31 of file lock.h.

◆ PROCLOCK

◆ PROCLOCKTAG

◆ VirtualTransactionId

Enumeration Type Documentation

◆ DeadLockState

Enumerator
DS_NOT_YET_CHECKED 
DS_NO_DEADLOCK 
DS_SOFT_DEADLOCK 
DS_HARD_DEADLOCK 
DS_BLOCKED_BY_AUTOVACUUM 

Definition at line 339 of file lock.h.

340{
341 DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
342 DS_NO_DEADLOCK, /* no deadlock detected */
343 DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
344 DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
345 DS_BLOCKED_BY_AUTOVACUUM, /* no deadlock; queue blocked by autovacuum
346 * worker */

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 
LOCKACQUIRE_ALREADY_CLEAR 

Definition at line 330 of file lock.h.

331{
332 LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
333 LOCKACQUIRE_OK, /* lock successfully acquired */
334 LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
335 LOCKACQUIRE_ALREADY_CLEAR, /* incremented count for lock already clear */

Function Documentation

◆ AbortStrongLockAcquire()

void AbortStrongLockAcquire ( void  )
extern

Definition at line 1869 of file lock.c.

1870{
1873
1874 if (locallock == NULL)
1875 return;
1876
1878 Assert(locallock->holdsStrongLockCount == true);
1882 locallock->holdsStrongLockCount = false;
1885}
#define Assert(condition)
Definition c.h:943
#define FastPathStrongLockHashPartition(hashcode)
Definition lock.c:306
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition lock.c:315
static LOCALLOCK * StrongLockInProgress
Definition lock.c:338
static void SpinLockRelease(volatile slock_t *lock)
Definition spin.h:62
static void SpinLockAcquire(volatile slock_t *lock)
Definition spin.h:56
uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS]
Definition lock.c:312

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

Referenced by LockAcquireExtended(), and LockErrorCleanup().

◆ AtPrepare_Locks()

void AtPrepare_Locks ( void  )
extern

Definition at line 3485 of file lock.c.

3486{
3487 HASH_SEQ_STATUS status;
3489
3490 /* First, verify there aren't locks of both xact and session level */
3492
3493 /* Now do the per-locallock cleanup work */
3495
3496 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3497 {
3498 TwoPhaseLockRecord record;
3499 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3500 bool haveSessionLock;
3501 bool haveXactLock;
3502 int i;
3503
3504 /*
3505 * Ignore VXID locks. We don't want those to be held by prepared
3506 * transactions, since they aren't meaningful after a restart.
3507 */
3508 if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3509 continue;
3510
3511 /* Ignore it if we don't actually hold the lock */
3512 if (locallock->nLocks <= 0)
3513 continue;
3514
3515 /* Scan to see whether we hold it at session or transaction level */
3516 haveSessionLock = haveXactLock = false;
3517 for (i = locallock->numLockOwners - 1; i >= 0; i--)
3518 {
3519 if (lockOwners[i].owner == NULL)
3520 haveSessionLock = true;
3521 else
3522 haveXactLock = true;
3523 }
3524
3525 /* Ignore it if we have only session lock */
3526 if (!haveXactLock)
3527 continue;
3528
3529 /* This can't happen, because we already checked it */
3530 if (haveSessionLock)
3531 ereport(ERROR,
3533 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3534
3535 /*
3536 * If the local lock was taken via the fast-path, we need to move it
3537 * to the primary lock table, or just get a pointer to the existing
3538 * primary lock table entry if by chance it's already been
3539 * transferred.
3540 */
3541 if (locallock->proclock == NULL)
3542 {
3544 locallock->lock = locallock->proclock->tag.myLock;
3545 }
3546
3547 /*
3548 * Arrange to not release any strong lock count held by this lock
3549 * entry. We must retain the count until the prepared transaction is
3550 * committed or rolled back.
3551 */
3552 locallock->holdsStrongLockCount = false;
3553
3554 /*
3555 * Create a 2PC record.
3556 */
3557 memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3558 record.lockmode = locallock->tag.mode;
3559
3561 &record, sizeof(TwoPhaseLockRecord));
3562 }
3563}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1317
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
int i
Definition isn.c:77
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition lock.c:2967
static HTAB * LockMethodLocalHash
Definition lock.c:334
static void CheckForSessionAndXactLocks(void)
Definition lock.c:3397
@ LOCKTAG_VIRTUALTRANSACTION
Definition locktag.h:43
static char * errmsg
LOCKTAG locktag
Definition lock.c:163
LOCKMODE lockmode
Definition lock.c:164
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition twophase.c:1277
#define TWOPHASE_RM_LOCK_ID

References CheckForSessionAndXactLocks(), ereport, errcode(), errmsg, ERROR, FastPathGetRelationLockEntry(), fb(), hash_seq_init(), hash_seq_search(), i, LockMethodLocalHash, TwoPhaseLockRecord::lockmode, TwoPhaseLockRecord::locktag, LOCKTAG_VIRTUALTRANSACTION, memcpy(), RegisterTwoPhaseRecord(), and TWOPHASE_RM_LOCK_ID.

Referenced by PrepareTransaction().

◆ DeadLockCheck()

DeadLockState DeadLockCheck ( PGPROC proc)
extern

Definition at line 220 of file deadlock.c.

221{
222 /* Initialize to "no constraints" */
223 nCurConstraints = 0;
225 nWaitOrders = 0;
226
227 /* Initialize to not blocked by an autovacuum worker */
229
230 /* Search for deadlocks and possible fixes */
231 if (DeadLockCheckRecurse(proc))
232 {
233 /*
234 * Call FindLockCycle one more time, to record the correct
235 * deadlockDetails[] for the basic state with no rearrangements.
236 */
237 int nSoftEdges;
238
240
241 nWaitOrders = 0;
243 elog(FATAL, "deadlock seems to have disappeared");
244
245 return DS_HARD_DEADLOCK; /* cannot find a non-deadlocked state */
246 }
247
248 /* Apply any needed rearrangements of wait queues */
249 for (int i = 0; i < nWaitOrders; i++)
250 {
251 LOCK *lock = waitOrders[i].lock;
252 PGPROC **procs = waitOrders[i].procs;
253 int nProcs = waitOrders[i].nProcs;
255
256 Assert(nProcs == dclist_count(waitQueue));
257
258#ifdef DEBUG_DEADLOCK
259 PrintLockQueue(lock, "DeadLockCheck:");
260#endif
261
262 /* Reset the queue and re-add procs in the desired order */
264 for (int j = 0; j < nProcs; j++)
265 dclist_push_tail(waitQueue, &procs[j]->waitLink);
266
267#ifdef DEBUG_DEADLOCK
268 PrintLockQueue(lock, "rearranged to:");
269#endif
270
271 /* See if any waiters for the lock can be woken up now */
273 }
274
275 /* Return code tells caller if we had to escape a deadlock or not */
276 if (nWaitOrders > 0)
277 return DS_SOFT_DEADLOCK;
278 else if (blocking_autovacuum_proc != NULL)
280 else
281 return DS_NO_DEADLOCK;
282}
static WAIT_ORDER * waitOrders
Definition deadlock.c:112
static bool FindLockCycle(PGPROC *checkProc, EDGE *softEdges, int *nSoftEdges)
Definition deadlock.c:446
static bool DeadLockCheckRecurse(PGPROC *proc)
Definition deadlock.c:312
static EDGE * possibleConstraints
Definition deadlock.c:122
static int nWaitOrders
Definition deadlock.c:113
static int nCurConstraints
Definition deadlock.c:118
static PGPROC * blocking_autovacuum_proc
Definition deadlock.c:129
static int nPossibleConstraints
Definition deadlock.c:123
#define FATAL
Definition elog.h:42
#define elog(elevel,...)
Definition elog.h:228
static void dclist_push_tail(dclist_head *head, dlist_node *node)
Definition ilist.h:709
static uint32 dclist_count(const dclist_head *head)
Definition ilist.h:932
static void dclist_init(dclist_head *head)
Definition ilist.h:671
int j
Definition isn.c:78
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition lock.c:525
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition proc.c:1776
PGPROC ** procs
Definition deadlock.c:60
LOCK * lock
Definition deadlock.c:59
int nProcs
Definition deadlock.c:61

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

Referenced by CheckDeadLock().

◆ DeadLockReport()

pg_noreturn void DeadLockReport ( void  )
extern

Definition at line 1075 of file deadlock.c.

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

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

Referenced by LockAcquireExtended().

◆ DoLockModesConflict()

bool DoLockModesConflict ( LOCKMODE  mode1,
LOCKMODE  mode2 
)
extern

Definition at line 621 of file lock.c.

622{
624
625 if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
626 return true;
627
628 return false;
629}
static const LockMethod LockMethods[]
Definition lock.c:153
#define LOCKBIT_ON(lockmode)
Definition lock.h:87
#define DEFAULT_LOCKMETHOD
Definition locktag.h:25

References DEFAULT_LOCKMETHOD, fb(), LOCKBIT_ON, and LockMethods.

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

◆ GetAwaitedLock()

LOCALLOCK * GetAwaitedLock ( void  )
extern

Definition at line 1907 of file lock.c.

1908{
1909 return awaitedLock;
1910}
static LOCALLOCK * awaitedLock
Definition lock.c:339

References awaitedLock.

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

◆ GetBlockerStatusData()

BlockedProcsData * GetBlockerStatusData ( int  blocked_pid)
extern

Definition at line 3980 of file lock.c.

3981{
3983 PGPROC *proc;
3984 int i;
3985
3987
3988 /*
3989 * Guess how much space we'll need, and preallocate. Most of the time
3990 * this will avoid needing to do repalloc while holding the LWLocks. (We
3991 * assume, but check with an Assert, that MaxBackends is enough entries
3992 * for the procs[] array; the other two could need enlargement, though.)
3993 */
3994 data->nprocs = data->nlocks = data->npids = 0;
3995 data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3996 data->procs = palloc_array(BlockedProcData, data->maxprocs);
3997 data->locks = palloc_array(LockInstanceData, data->maxlocks);
3998 data->waiter_pids = palloc_array(int, data->maxpids);
3999
4000 /*
4001 * In order to search the ProcArray for blocked_pid and assume that that
4002 * entry won't immediately disappear under us, we must hold ProcArrayLock.
4003 * In addition, to examine the lock grouping fields of any other backend,
4004 * we must hold all the hash partition locks. (Only one of those locks is
4005 * actually relevant for any one lock group, but we can't know which one
4006 * ahead of time.) It's fairly annoying to hold all those locks
4007 * throughout this, but it's no worse than GetLockStatusData(), and it
4008 * does have the advantage that we're guaranteed to return a
4009 * self-consistent instantaneous state.
4010 */
4012
4014
4015 /* Nothing to do if it's gone */
4016 if (proc != NULL)
4017 {
4018 /*
4019 * Acquire lock on the entire shared lock data structure. See notes
4020 * in GetLockStatusData().
4021 */
4022 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
4024
4025 if (proc->lockGroupLeader == NULL)
4026 {
4027 /* Easy case, proc is not a lock group member */
4029 }
4030 else
4031 {
4032 /* Examine all procs in proc's lock group */
4033 dlist_iter iter;
4034
4036 {
4038
4039 memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
4041 }
4042 }
4043
4044 /*
4045 * And release locks. See notes in GetLockStatusData().
4046 */
4047 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
4049
4050 Assert(data->nprocs <= data->maxprocs);
4051 }
4052
4054
4055 return data;
4056}
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc_array(type, count)
Definition fe_memutils.h:76
int MaxBackends
Definition globals.c:149
#define dlist_foreach(iter, lhead)
Definition ilist.h:623
#define dlist_container(type, membername, ptr)
Definition ilist.h:593
static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
Definition lock.c:4060
#define LockHashPartitionLockByIndex(i)
Definition lock.h:360
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
#define NUM_LOCK_PARTITIONS
Definition lwlock.h:87
@ LW_SHARED
Definition lwlock.h:105
const void * data
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3192
dlist_head lockGroupMembers
Definition proc.h:299
PGPROC * lockGroupLeader
Definition proc.h:298
dlist_node * cur
Definition ilist.h:179

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

Referenced by pg_blocking_pids().

◆ GetBlockingAutoVacuumPgproc()

PGPROC * GetBlockingAutoVacuumPgproc ( void  )
extern

Definition at line 290 of file deadlock.c.

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

References blocking_autovacuum_proc, and fb().

Referenced by ProcSleep().

◆ GetLockConflicts()

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

Definition at line 3078 of file lock.c.

3079{
3083 LOCK *lock;
3086 PROCLOCK *proclock;
3087 uint32 hashcode;
3089 int count = 0;
3090 int fast_count = 0;
3091
3093 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
3096 elog(ERROR, "unrecognized lock mode: %d", lockmode);
3097
3098 /*
3099 * Allocate memory to store results, and fill with InvalidVXID. We only
3100 * need enough space for MaxBackends + max_prepared_xacts + a terminator.
3101 * InHotStandby allocate once in TopMemoryContext.
3102 */
3103 if (InHotStandby)
3104 {
3105 if (vxids == NULL)
3108 sizeof(VirtualTransactionId) *
3110 }
3111 else
3113
3114 /* Compute hash code and partition lock, and look up conflicting modes. */
3115 hashcode = LockTagHashCode(locktag);
3117 conflictMask = lockMethodTable->conflictTab[lockmode];
3118
3119 /*
3120 * Fast path locks might not have been entered in the primary lock table.
3121 * If the lock we're dealing with could conflict with such a lock, we must
3122 * examine each backend's fast-path array for conflicts.
3123 */
3124 if (ConflictsWithRelationFastPath(locktag, lockmode))
3125 {
3126 int i;
3127 Oid relid = locktag->locktag_field2;
3129
3130 /* fast-path group the lock belongs to */
3131 uint32 group = FAST_PATH_REL_GROUP(relid);
3132
3133 /*
3134 * Iterate over relevant PGPROCs. Anything held by a prepared
3135 * transaction will have been transferred to the primary lock table,
3136 * so we need not worry about those. This is all a bit fuzzy, because
3137 * new locks could be taken after we've visited a particular
3138 * partition, but the callers had better be prepared to deal with that
3139 * anyway, since the locks could equally well be taken between the
3140 * time we return the value and the time the caller does something
3141 * with it.
3142 */
3143 for (i = 0; i < ProcGlobal->allProcCount; i++)
3144 {
3145 PGPROC *proc = GetPGProcByNumber(i);
3146 uint32 j;
3147
3148 /* A backend never blocks itself */
3149 if (proc == MyProc)
3150 continue;
3151
3153
3154 /*
3155 * If the target backend isn't referencing the same database as
3156 * the lock, then we needn't examine the individual relation IDs
3157 * at all; none of them can be relevant.
3158 *
3159 * See FastPathTransferRelationLocks() for discussion of why we do
3160 * this test after acquiring the lock.
3161 *
3162 * Also skip groups without any registered fast-path locks.
3163 */
3164 if (proc->databaseId != locktag->locktag_field1 ||
3165 proc->fpLockBits[group] == 0)
3166 {
3167 LWLockRelease(&proc->fpInfoLock);
3168 continue;
3169 }
3170
3171 for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++)
3172 {
3174
3175 /* index into the whole per-backend array */
3176 uint32 f = FAST_PATH_SLOT(group, j);
3177
3178 /* Look for an allocated slot matching the given relid. */
3179 if (relid != proc->fpRelId[f])
3180 continue;
3181 lockmask = FAST_PATH_GET_BITS(proc, f);
3182 if (!lockmask)
3183 continue;
3185
3186 /*
3187 * There can only be one entry per relation, so if we found it
3188 * and it doesn't conflict, we can skip the rest of the slots.
3189 */
3190 if ((lockmask & conflictMask) == 0)
3191 break;
3192
3193 /* Conflict! */
3194 GET_VXID_FROM_PGPROC(vxid, *proc);
3195
3197 vxids[count++] = vxid;
3198 /* else, xact already committed or aborted */
3199
3200 /* No need to examine remaining slots. */
3201 break;
3202 }
3203
3204 LWLockRelease(&proc->fpInfoLock);
3205 }
3206 }
3207
3208 /* Remember how many fast-path conflicts we found. */
3209 fast_count = count;
3210
3211 /*
3212 * Look up the lock object matching the tag.
3213 */
3215
3217 locktag,
3218 hashcode,
3219 HASH_FIND,
3220 NULL);
3221 if (!lock)
3222 {
3223 /*
3224 * If the lock object doesn't exist, there is nothing holding a lock
3225 * on this lockable object.
3226 */
3228 vxids[count].procNumber = INVALID_PROC_NUMBER;
3229 vxids[count].localTransactionId = InvalidLocalTransactionId;
3230 if (countp)
3231 *countp = count;
3232 return vxids;
3233 }
3234
3235 /*
3236 * Examine each existing holder (or awaiter) of the lock.
3237 */
3239 {
3240 proclock = dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
3241
3242 if (conflictMask & proclock->holdMask)
3243 {
3244 PGPROC *proc = proclock->tag.myProc;
3245
3246 /* A backend never blocks itself */
3247 if (proc != MyProc)
3248 {
3250
3251 GET_VXID_FROM_PGPROC(vxid, *proc);
3252
3254 {
3255 int i;
3256
3257 /* Avoid duplicate entries. */
3258 for (i = 0; i < fast_count; ++i)
3260 break;
3261 if (i >= fast_count)
3262 vxids[count++] = vxid;
3263 }
3264 /* else, xact already committed or aborted */
3265 }
3266 }
3267 }
3268
3270
3271 if (count > MaxBackends + max_prepared_xacts) /* should never happen */
3272 elog(PANIC, "too many conflicting locks found");
3273
3274 vxids[count].procNumber = INVALID_PROC_NUMBER;
3275 vxids[count].localTransactionId = InvalidLocalTransactionId;
3276 if (countp)
3277 *countp = count;
3278 return vxids;
3279}
#define lengthof(array)
Definition c.h:873
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition dynahash.c:902
#define PANIC
Definition elog.h:44
#define palloc0_array(type, count)
Definition fe_memutils.h:77
@ HASH_FIND
Definition hsearch.h:108
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition lock.c:245
#define FAST_PATH_REL_GROUP(rel)
Definition lock.c:220
#define FAST_PATH_SLOT(group, index)
Definition lock.c:227
#define ConflictsWithRelationFastPath(locktag, mode)
Definition lock.c:276
static HTAB * LockMethodLockHash
Definition lock.c:332
#define FAST_PATH_GET_BITS(proc, n)
Definition lock.c:248
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:555
#define VirtualTransactionIdIsValid(vxid)
Definition lock.h:70
#define LockHashPartitionLock(hashcode)
Definition lock.h:357
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:80
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition lock.h:74
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
MemoryContext TopMemoryContext
Definition mcxt.c:166
unsigned int Oid
#define GetPGProcByNumber(n)
Definition proc.h:504
#define FP_LOCK_SLOTS_PER_GROUP
Definition proc.h:96
PGPROC * MyProc
Definition proc.c:71
PROC_HDR * ProcGlobal
Definition proc.c:74
uint32 locktag_field1
Definition locktag.h:66
uint32 locktag_field2
Definition locktag.h:67
LWLock fpInfoLock
Definition proc.h:324
Oid * fpRelId
Definition proc.h:326
Oid databaseId
Definition proc.h:201
uint64 * fpLockBits
Definition proc.h:325
uint32 allProcCount
Definition proc.h:459
int max_prepared_xacts
Definition twophase.c:118
#define InHotStandby
Definition xlogutils.h:60

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

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

◆ GetLockmodeName()

const char * GetLockmodeName ( LOCKMETHODID  lockmethodid,
LOCKMODE  mode 
)
extern

◆ GetLocksMethodTable()

LockMethod GetLocksMethodTable ( const LOCK lock)
extern

Definition at line 525 of file lock.c.

526{
528
531}
#define LOCK_LOCKMETHOD(lock)
Definition lock.h:155

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

Referenced by DeadLockCheck(), and FindLockCycleRecurseMember().

◆ GetLockStatusData()

LockData * GetLockStatusData ( void  )
extern

Definition at line 3777 of file lock.c.

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

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

Referenced by pg_lock_status().

◆ GetLockTagsMethodTable()

LockMethod GetLockTagsMethodTable ( const LOCKTAG locktag)
extern

Definition at line 537 of file lock.c.

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

Referenced by pg_blocking_pids().

◆ GetRunningTransactionLocks()

xl_standby_lock * GetRunningTransactionLocks ( int nlocks)
extern

Definition at line 4154 of file lock.c.

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

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

Referenced by LogStandbySnapshot().

◆ GrantAwaitedLock()

void GrantAwaitedLock ( void  )
extern

Definition at line 1898 of file lock.c.

1899{
1901}
static ResourceOwner awaitedOwner
Definition lock.c:340
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition lock.c:1801

References awaitedLock, awaitedOwner, and GrantLockLocal().

Referenced by LockErrorCleanup().

◆ GrantLock()

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

Definition at line 1667 of file lock.c.

1668{
1669 lock->nGranted++;
1670 lock->granted[lockmode]++;
1671 lock->grantMask |= LOCKBIT_ON(lockmode);
1672 if (lock->granted[lockmode] == lock->requested[lockmode])
1673 lock->waitMask &= LOCKBIT_OFF(lockmode);
1674 proclock->holdMask |= LOCKBIT_ON(lockmode);
1675 LOCK_PRINT("GrantLock", lock, lockmode);
1676 Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1677 Assert(lock->nGranted <= lock->nRequested);
1678}
#define LOCK_PRINT(where, lock, type)
Definition lock.c:416
#define LOCKBIT_OFF(lockmode)
Definition lock.h:88

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

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

◆ InitDeadLockChecking()

void InitDeadLockChecking ( void  )
extern

Definition at line 143 of file deadlock.c.

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

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

Referenced by InitProcess().

◆ InitLockManagerAccess()

void InitLockManagerAccess ( void  )
extern

Definition at line 503 of file lock.c.

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

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

Referenced by BaseInit().

◆ lock_twophase_postabort()

void lock_twophase_postabort ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 4579 of file lock.c.

4581{
4582 lock_twophase_postcommit(fxid, info, recdata, len);
4583}
void lock_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4553

References fb(), len, and lock_twophase_postcommit().

◆ lock_twophase_postcommit()

void lock_twophase_postcommit ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 4553 of file lock.c.

4555{
4557 PGPROC *proc = TwoPhaseGetDummyProc(fxid, true);
4558 LOCKTAG *locktag;
4561
4562 Assert(len == sizeof(TwoPhaseLockRecord));
4563 locktag = &rec->locktag;
4565
4567 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4569
4570 LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4571}
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition lock.c:3293
PGPROC * TwoPhaseGetDummyProc(FullTransactionId fxid, bool lock_held)
Definition twophase.c:929

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

Referenced by lock_twophase_postabort().

◆ lock_twophase_recover()

void lock_twophase_recover ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 4340 of file lock.c.

4342{
4344 PGPROC *proc = TwoPhaseGetDummyProc(fxid, false);
4345 LOCKTAG *locktag;
4346 LOCKMODE lockmode;
4348 LOCK *lock;
4349 PROCLOCK *proclock;
4351 bool found;
4352 uint32 hashcode;
4354 int partition;
4357
4358 Assert(len == sizeof(TwoPhaseLockRecord));
4359 locktag = &rec->locktag;
4360 lockmode = rec->lockmode;
4362
4364 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4366
4367 hashcode = LockTagHashCode(locktag);
4368 partition = LockHashPartition(hashcode);
4370
4372
4373 /*
4374 * Find or create a lock with this tag.
4375 */
4377 locktag,
4378 hashcode,
4380 &found);
4381 if (!lock)
4382 {
4384 ereport(ERROR,
4386 errmsg("out of shared memory"),
4387 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4388 }
4389
4390 /*
4391 * if it's a new lock object, initialize it
4392 */
4393 if (!found)
4394 {
4395 lock->grantMask = 0;
4396 lock->waitMask = 0;
4397 dlist_init(&lock->procLocks);
4398 dclist_init(&lock->waitProcs);
4399 lock->nRequested = 0;
4400 lock->nGranted = 0;
4401 MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4402 MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4403 LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4404 }
4405 else
4406 {
4407 LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4408 Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4409 Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4410 Assert(lock->nGranted <= lock->nRequested);
4411 }
4412
4413 /*
4414 * Create the hash key for the proclock table.
4415 */
4416 proclocktag.myLock = lock;
4417 proclocktag.myProc = proc;
4418
4420
4421 /*
4422 * Find or create a proclock entry with this tag
4423 */
4425 &proclocktag,
4428 &found);
4429 if (!proclock)
4430 {
4431 /* Oops, not enough shmem for the proclock */
4432 if (lock->nRequested == 0)
4433 {
4434 /*
4435 * There are no other requestors of this lock, so garbage-collect
4436 * the lock object. We *must* do this to avoid a permanent leak
4437 * of shared memory, because there won't be anything to cause
4438 * anyone to release the lock object later.
4439 */
4442 &(lock->tag),
4443 hashcode,
4445 NULL))
4446 elog(PANIC, "lock table corrupted");
4447 }
4449 ereport(ERROR,
4451 errmsg("out of shared memory"),
4452 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4453 }
4454
4455 /*
4456 * If new, initialize the new entry
4457 */
4458 if (!found)
4459 {
4460 Assert(proc->lockGroupLeader == NULL);
4461 proclock->groupLeader = proc;
4462 proclock->holdMask = 0;
4463 proclock->releaseMask = 0;
4464 /* Add proclock to appropriate lists */
4465 dlist_push_tail(&lock->procLocks, &proclock->lockLink);
4467 &proclock->procLink);
4468 PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4469 }
4470 else
4471 {
4472 PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4473 Assert((proclock->holdMask & ~lock->grantMask) == 0);
4474 }
4475
4476 /*
4477 * lock->nRequested and lock->requested[] count the total number of
4478 * requests, whether granted or waiting, so increment those immediately.
4479 */
4480 lock->nRequested++;
4481 lock->requested[lockmode]++;
4482 Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4483
4484 /*
4485 * We shouldn't already hold the desired lock.
4486 */
4487 if (proclock->holdMask & LOCKBIT_ON(lockmode))
4488 elog(ERROR, "lock %s on object %u/%u/%u is already held",
4489 lockMethodTable->lockModeNames[lockmode],
4490 lock->tag.locktag_field1, lock->tag.locktag_field2,
4491 lock->tag.locktag_field3);
4492
4493 /*
4494 * We ignore any possible conflicts and just grant ourselves the lock. Not
4495 * only because we don't bother, but also to avoid deadlocks when
4496 * switching from standby to normal mode. See function comment.
4497 */
4498 GrantLock(lock, proclock, lockmode);
4499
4500 /*
4501 * Bump strong lock count, to make sure any fast-path lock requests won't
4502 * be granted without consulting the primary lock table.
4503 */
4504 if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4505 {
4507
4511 }
4512
4514}
#define MemSet(start, val, len)
Definition c.h:1107
@ HASH_REMOVE
Definition hsearch.h:110
@ HASH_ENTER_NULL
Definition hsearch.h:111
static void dlist_init(dlist_head *head)
Definition ilist.h:314
static bool dlist_is_empty(const dlist_head *head)
Definition ilist.h:336
static void dlist_push_tail(dlist_head *head, dlist_node *node)
Definition ilist.h:364
static uint32 ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
Definition lock.c:603
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1667
#define PROCLOCK_PRINT(where, proclockP)
Definition lock.c:417
#define LockHashPartition(hashcode)
Definition lock.h:355
@ LW_EXCLUSIVE
Definition lwlock.h:104
uint32 locktag_field3
Definition locktag.h:68
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition proc.h:321

References Assert, ConflictsWithRelationFastPath, FastPathStrongRelationLockData::count, dclist_init(), dlist_init(), dlist_is_empty(), dlist_push_tail(), elog, ereport, errcode(), errhint(), errmsg, ERROR, FastPathStrongLockHashPartition, FastPathStrongRelationLocks, fb(), LOCK::granted, GrantLock(), LOCK::grantMask, PROCLOCK::groupLeader, HASH_ENTER_NULL, HASH_REMOVE, hash_search_with_hash_value(), PROCLOCK::holdMask, len, lengthof, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartition, LockHashPartitionLock, PROCLOCK::lockLink, LockMethodLockHash, LockMethodProcLockHash, LockMethods, TwoPhaseLockRecord::lockmode, TwoPhaseLockRecord::locktag, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_field3, LOCKTAG::locktag_lockmethodid, LockTagHashCode(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MAX_LOCKMODES, MemSet, FastPathStrongRelationLockData::mutex, PGPROC::myProcLocks, LOCK::nGranted, LOCK::nRequested, PANIC, PROCLOCK::procLink, PROCLOCK_PRINT, ProcLockHashCode(), LOCK::procLocks, PROCLOCK::releaseMask, LOCK::requested, SpinLockAcquire(), SpinLockRelease(), LOCK::tag, TwoPhaseGetDummyProc(), LOCK::waitMask, and LOCK::waitProcs.

◆ lock_twophase_standby_recover()

void lock_twophase_standby_recover ( FullTransactionId  fxid,
uint16  info,
void recdata,
uint32  len 
)
extern

Definition at line 4521 of file lock.c.

4523{
4525 LOCKTAG *locktag;
4526 LOCKMODE lockmode;
4528
4529 Assert(len == sizeof(TwoPhaseLockRecord));
4530 locktag = &rec->locktag;
4531 lockmode = rec->lockmode;
4533
4535 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4536
4537 if (lockmode == AccessExclusiveLock &&
4538 locktag->locktag_type == LOCKTAG_RELATION)
4539 {
4541 locktag->locktag_field1 /* dboid */ ,
4542 locktag->locktag_field2 /* reloid */ );
4543 }
4544}
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition standby.c:988
#define XidFromFullTransactionId(x)
Definition transam.h:48

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

◆ LockAcquire()

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

◆ LockAcquireExtended()

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

Definition at line 834 of file lock.c.

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

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

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

◆ LockCheckConflicts()

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

Definition at line 1538 of file lock.c.

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

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

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

◆ LockHasWaiters()

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

Definition at line 694 of file lock.c.

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

References elog, ERROR, fb(), HASH_FIND, hash_search(), PROCLOCK::holdMask, lengthof, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLock, LockMethodLocalHash, LockMethods, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOG, LW_SHARED, LWLockAcquire(), LWLockRelease(), MemSet, PROCLOCK_PRINT, RemoveLocalLock(), LOCK::waitMask, and WARNING.

Referenced by LockHasWaitersRelation().

◆ LockHeldByMe()

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

Definition at line 641 of file lock.c.

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

References fb(), HASH_FIND, hash_search(), LockHeldByMe(), LockMethodLocalHash, MaxLockMode, and MemSet.

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

◆ LockReassignCurrentOwner()

void LockReassignCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)
extern

Definition at line 2715 of file lock.c.

2716{
2718
2719 Assert(parent != NULL);
2720
2721 if (locallocks == NULL)
2722 {
2723 HASH_SEQ_STATUS status;
2725
2727
2728 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2730 }
2731 else
2732 {
2733 int i;
2734
2735 for (i = nlocks - 1; i >= 0; i--)
2736 LockReassignOwner(locallocks[i], parent);
2737 }
2738}
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition lock.c:2745
ResourceOwner ResourceOwnerGetParent(ResourceOwner owner)
Definition resowner.c:902

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

Referenced by ResourceOwnerReleaseInternal().

◆ LockRelease()

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

Definition at line 2111 of file lock.c.

2112{
2117 LOCK *lock;
2118 PROCLOCK *proclock;
2120 bool wakeupNeeded;
2121
2123 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2126 elog(ERROR, "unrecognized lock mode: %d", lockmode);
2127
2128#ifdef LOCK_DEBUG
2129 if (LOCK_DEBUG_ENABLED(locktag))
2130 elog(LOG, "LockRelease: lock [%u,%u] %s",
2131 locktag->locktag_field1, locktag->locktag_field2,
2132 lockMethodTable->lockModeNames[lockmode]);
2133#endif
2134
2135 /*
2136 * Find the LOCALLOCK entry for this lock and lockmode
2137 */
2138 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
2139 localtag.lock = *locktag;
2140 localtag.mode = lockmode;
2141
2143 &localtag,
2144 HASH_FIND, NULL);
2145
2146 /*
2147 * let the caller print its own error message, too. Do not ereport(ERROR).
2148 */
2149 if (!locallock || locallock->nLocks <= 0)
2150 {
2151 elog(WARNING, "you don't own a lock of type %s",
2152 lockMethodTable->lockModeNames[lockmode]);
2153 return false;
2154 }
2155
2156 /*
2157 * Decrease the count for the resource owner.
2158 */
2159 {
2160 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2161 ResourceOwner owner;
2162 int i;
2163
2164 /* Identify owner for lock */
2165 if (sessionLock)
2166 owner = NULL;
2167 else
2168 owner = CurrentResourceOwner;
2169
2170 for (i = locallock->numLockOwners - 1; i >= 0; i--)
2171 {
2172 if (lockOwners[i].owner == owner)
2173 {
2174 Assert(lockOwners[i].nLocks > 0);
2175 if (--lockOwners[i].nLocks == 0)
2176 {
2177 if (owner != NULL)
2179 /* compact out unused slot */
2180 locallock->numLockOwners--;
2181 if (i < locallock->numLockOwners)
2182 lockOwners[i] = lockOwners[locallock->numLockOwners];
2183 }
2184 break;
2185 }
2186 }
2187 if (i < 0)
2188 {
2189 /* don't release a lock belonging to another owner */
2190 elog(WARNING, "you don't own a lock of type %s",
2191 lockMethodTable->lockModeNames[lockmode]);
2192 return false;
2193 }
2194 }
2195
2196 /*
2197 * Decrease the total local count. If we're still holding the lock, we're
2198 * done.
2199 */
2200 locallock->nLocks--;
2201
2202 if (locallock->nLocks > 0)
2203 return true;
2204
2205 /*
2206 * At this point we can no longer suppose we are clear of invalidation
2207 * messages related to this lock. Although we'll delete the LOCALLOCK
2208 * object before any intentional return from this routine, it seems worth
2209 * the trouble to explicitly reset lockCleared right now, just in case
2210 * some error prevents us from deleting the LOCALLOCK.
2211 */
2212 locallock->lockCleared = false;
2213
2214 /* Attempt fast release of any lock eligible for the fast path. */
2215 if (EligibleForRelationFastPath(locktag, lockmode) &&
2217 {
2218 bool released;
2219
2220 /*
2221 * We might not find the lock here, even if we originally entered it
2222 * here. Another backend may have moved it to the main table.
2223 */
2226 lockmode);
2228 if (released)
2229 {
2231 return true;
2232 }
2233 }
2234
2235 /*
2236 * Otherwise we've got to mess with the shared lock table.
2237 */
2239
2241
2242 /*
2243 * Normally, we don't need to re-find the lock or proclock, since we kept
2244 * their addresses in the locallock table, and they couldn't have been
2245 * removed while we were holding a lock on them. But it's possible that
2246 * the lock was taken fast-path and has since been moved to the main hash
2247 * table by another backend, in which case we will need to look up the
2248 * objects here. We assume the lock field is NULL if so.
2249 */
2250 lock = locallock->lock;
2251 if (!lock)
2252 {
2254
2255 Assert(EligibleForRelationFastPath(locktag, lockmode));
2257 locktag,
2258 locallock->hashcode,
2259 HASH_FIND,
2260 NULL);
2261 if (!lock)
2262 elog(ERROR, "failed to re-find shared lock object");
2263 locallock->lock = lock;
2264
2265 proclocktag.myLock = lock;
2266 proclocktag.myProc = MyProc;
2268 &proclocktag,
2269 HASH_FIND,
2270 NULL);
2271 if (!locallock->proclock)
2272 elog(ERROR, "failed to re-find shared proclock object");
2273 }
2274 LOCK_PRINT("LockRelease: found", lock, lockmode);
2275 proclock = locallock->proclock;
2276 PROCLOCK_PRINT("LockRelease: found", proclock);
2277
2278 /*
2279 * Double-check that we are actually holding a lock of the type we want to
2280 * release.
2281 */
2282 if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2283 {
2284 PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
2286 elog(WARNING, "you don't own a lock of type %s",
2287 lockMethodTable->lockModeNames[lockmode]);
2289 return false;
2290 }
2291
2292 /*
2293 * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2294 */
2295 wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2296
2297 CleanUpLock(lock, proclock,
2298 lockMethodTable, locallock->hashcode,
2299 wakeupNeeded);
2300
2302
2304 return true;
2305}
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode, PROCLOCK *proclock, LockMethod lockMethodTable)
Definition lock.c:1690
static void CleanUpLock(LOCK *lock, PROCLOCK *proclock, LockMethod lockMethodTable, uint32 hashcode, bool wakeupNeeded)
Definition lock.c:1747
static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition lock.c:2834
void ResourceOwnerForgetLock(ResourceOwner owner, LOCALLOCK *locallock)
Definition resowner.c:1079

References Assert, CleanUpLock(), CurrentResourceOwner, EligibleForRelationFastPath, elog, ERROR, FAST_PATH_REL_GROUP, FastPathLocalUseCounts, FastPathUnGrantRelationLock(), fb(), PGPROC::fpInfoLock, HASH_FIND, hash_search(), hash_search_with_hash_value(), PROCLOCK::holdMask, i, lengthof, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLock, LockMethodLocalHash, LockMethodLockHash, LockMethodProcLockHash, LockMethods, LOCKTAG::locktag_field1, LOCKTAG::locktag_field2, LOCKTAG::locktag_lockmethodid, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, MyProc, PROCLOCK_PRINT, RemoveLocalLock(), ResourceOwnerForgetLock(), UnGrantLock(), and WARNING.

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

◆ LockReleaseAll()

void LockReleaseAll ( LOCKMETHODID  lockmethodid,
bool  allLocks 
)
extern

Definition at line 2316 of file lock.c.

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

References Assert, CleanUpLock(), DEFAULT_LOCKMETHOD, dlist_container, dlist_foreach_modify, dlist_is_empty(), EligibleForRelationFastPath, elog, ERROR, FastPathUnGrantRelationLock(), fb(), PGPROC::fpInfoLock, LOCK::grantMask, hash_seq_init(), hash_seq_search(), PROCLOCK::holdMask, i, lengthof, LOCALLOCK_LOCKMETHOD, LOCALLOCK_LOCKTAG, LOCK_LOCKMETHOD, LOCK_PRINT, LOCKBIT_ON, LockHashPartitionLockByIndex, LockMethodLocalHash, LockMethods, LockRefindAndRelease(), LOCKTAG_TUPLE, LockTagHashCode(), LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCALLOCKOWNER::nLocks, LOCK::nRequested, NUM_LOCK_PARTITIONS, LOCALLOCKOWNER::owner, PANIC, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), ResourceOwnerForgetLock(), LOCK::tag, PROCLOCK::tag, UnGrantLock(), VirtualXactLockTableCleanup(), and WARNING.

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

◆ LockReleaseCurrentOwner()

void LockReleaseCurrentOwner ( LOCALLOCK **  locallocks,
int  nlocks 
)
extern

Definition at line 2620 of file lock.c.

2621{
2622 if (locallocks == NULL)
2623 {
2624 HASH_SEQ_STATUS status;
2626
2628
2629 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2631 }
2632 else
2633 {
2634 int i;
2635
2636 for (i = nlocks - 1; i >= 0; i--)
2638 }
2639}
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition lock.c:2655

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

Referenced by ResourceOwnerReleaseInternal().

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)
extern

Definition at line 2590 of file lock.c.

2591{
2592 HASH_SEQ_STATUS status;
2594
2596 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2597
2599
2600 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2601 {
2602 /* Ignore items that are not of the specified lock method */
2604 continue;
2605
2607 }
2608}

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

Referenced by pg_advisory_unlock_all().

◆ LockTagHashCode()

uint32 LockTagHashCode ( const LOCKTAG locktag)
extern

Definition at line 555 of file lock.c.

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

References get_hash_value(), and LockMethodLockHash.

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

◆ LockWaiterCount()

int LockWaiterCount ( const LOCKTAG locktag)
extern

Definition at line 4837 of file lock.c.

4838{
4840 LOCK *lock;
4841 bool found;
4842 uint32 hashcode;
4844 int waiters = 0;
4845
4847 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4848
4849 hashcode = LockTagHashCode(locktag);
4852
4854 locktag,
4855 hashcode,
4856 HASH_FIND,
4857 &found);
4858 if (found)
4859 {
4860 Assert(lock != NULL);
4861 waiters = lock->nRequested;
4862 }
4864
4865 return waiters;
4866}

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

Referenced by RelationExtensionLockWaiterCount().

◆ MarkLockClear()

void MarkLockClear ( LOCALLOCK locallock)
extern

Definition at line 1929 of file lock.c.

1930{
1931 Assert(locallock->nLocks > 0);
1932 locallock->lockCleared = true;
1933}

References Assert, and fb().

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

◆ PostPrepare_Locks()

void PostPrepare_Locks ( FullTransactionId  fxid)
extern

Definition at line 3581 of file lock.c.

3582{
3583 PGPROC *newproc = TwoPhaseGetDummyProc(fxid, false);
3584 HASH_SEQ_STATUS status;
3586 LOCK *lock;
3587 PROCLOCK *proclock;
3589 int partition;
3590
3591 /* Can't prepare a lock group follower. */
3594
3595 /* This is a critical section: any error means big trouble */
3597
3598 /*
3599 * First we run through the locallock table and get rid of unwanted
3600 * entries, then we scan the process's proclocks and transfer them to the
3601 * target proc.
3602 *
3603 * We do this separately because we may have multiple locallock entries
3604 * pointing to the same proclock, and we daren't end up with any dangling
3605 * pointers.
3606 */
3608
3609 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3610 {
3611 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3612 bool haveSessionLock;
3613 bool haveXactLock;
3614 int i;
3615
3616 if (locallock->proclock == NULL || locallock->lock == NULL)
3617 {
3618 /*
3619 * We must've run out of shared memory while trying to set up this
3620 * lock. Just forget the local entry.
3621 */
3622 Assert(locallock->nLocks == 0);
3624 continue;
3625 }
3626
3627 /* Ignore VXID locks */
3628 if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3629 continue;
3630
3631 /* Scan to see whether we hold it at session or transaction level */
3632 haveSessionLock = haveXactLock = false;
3633 for (i = locallock->numLockOwners - 1; i >= 0; i--)
3634 {
3635 if (lockOwners[i].owner == NULL)
3636 haveSessionLock = true;
3637 else
3638 haveXactLock = true;
3639 }
3640
3641 /* Ignore it if we have only session lock */
3642 if (!haveXactLock)
3643 continue;
3644
3645 /* This can't happen, because we already checked it */
3646 if (haveSessionLock)
3647 ereport(PANIC,
3649 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3650
3651 /* Mark the proclock to show we need to release this lockmode */
3652 if (locallock->nLocks > 0)
3653 locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3654
3655 /* And remove the locallock hashtable entry */
3657 }
3658
3659 /*
3660 * Now, scan each lock partition separately.
3661 */
3663 {
3665 dlist_head *procLocks = &(MyProc->myProcLocks[partition]);
3667
3669
3670 /*
3671 * If the proclock list for this partition is empty, we can skip
3672 * acquiring the partition lock. This optimization is safer than the
3673 * situation in LockReleaseAll, because we got rid of any fast-path
3674 * locks during AtPrepare_Locks, so there cannot be any case where
3675 * another backend is adding something to our lists now. For safety,
3676 * though, we code this the same way as in LockReleaseAll.
3677 */
3678 if (dlist_is_empty(procLocks))
3679 continue; /* needn't examine this partition */
3680
3682
3684 {
3685 proclock = dlist_container(PROCLOCK, procLink, proclock_iter.cur);
3686
3687 Assert(proclock->tag.myProc == MyProc);
3688
3689 lock = proclock->tag.myLock;
3690
3691 /* Ignore VXID locks */
3693 continue;
3694
3695 PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3696 LOCK_PRINT("PostPrepare_Locks", lock, 0);
3697 Assert(lock->nRequested >= 0);
3698 Assert(lock->nGranted >= 0);
3699 Assert(lock->nGranted <= lock->nRequested);
3700 Assert((proclock->holdMask & ~lock->grantMask) == 0);
3701
3702 /* Ignore it if nothing to release (must be a session lock) */
3703 if (proclock->releaseMask == 0)
3704 continue;
3705
3706 /* Else we should be releasing all locks */
3707 if (proclock->releaseMask != proclock->holdMask)
3708 elog(PANIC, "we seem to have dropped a bit somewhere");
3709
3710 /*
3711 * We cannot simply modify proclock->tag.myProc to reassign
3712 * ownership of the lock, because that's part of the hash key and
3713 * the proclock would then be in the wrong hash chain. Instead
3714 * use hash_update_hash_key. (We used to create a new hash entry,
3715 * but that risks out-of-memory failure if other processes are
3716 * busy making proclocks too.) We must unlink the proclock from
3717 * our procLink chain and put it into the new proc's chain, too.
3718 *
3719 * Note: the updated proclock hash key will still belong to the
3720 * same hash partition, cf proclock_hash(). So the partition lock
3721 * we already hold is sufficient for this.
3722 */
3723 dlist_delete(&proclock->procLink);
3724
3725 /*
3726 * Create the new hash key for the proclock.
3727 */
3728 proclocktag.myLock = lock;
3729 proclocktag.myProc = newproc;
3730
3731 /*
3732 * Update groupLeader pointer to point to the new proc. (We'd
3733 * better not be a member of somebody else's lock group!)
3734 */
3735 Assert(proclock->groupLeader == proclock->tag.myProc);
3736 proclock->groupLeader = newproc;
3737
3738 /*
3739 * Update the proclock. We should not find any existing entry for
3740 * the same hash key, since there can be only one entry for any
3741 * given lock with my own proc.
3742 */
3744 proclock,
3745 &proclocktag))
3746 elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3747
3748 /* Re-link into the new proc's proclock list */
3749 dlist_push_tail(&newproc->myProcLocks[partition], &proclock->procLink);
3750
3751 PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
3752 } /* loop over PROCLOCKs within this partition */
3753
3755 } /* loop over partitions */
3756
3758}
bool hash_update_hash_key(HTAB *hashp, void *existingEntry, const void *newKeyPtr)
Definition dynahash.c:1077
#define START_CRIT_SECTION()
Definition miscadmin.h:152
#define END_CRIT_SECTION()
Definition miscadmin.h:154

References Assert, dlist_container, dlist_delete(), dlist_foreach_modify, dlist_is_empty(), dlist_push_tail(), elog, END_CRIT_SECTION, ereport, errcode(), errmsg, fb(), LOCK::grantMask, PROCLOCK::groupLeader, hash_seq_init(), hash_seq_search(), hash_update_hash_key(), PROCLOCK::holdMask, i, LOCK_PRINT, LOCKBIT_ON, PGPROC::lockGroupLeader, LockHashPartitionLockByIndex, LockMethodLocalHash, LockMethodProcLockHash, LOCKTAG::locktag_type, LOCKTAG_VIRTUALTRANSACTION, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PROCLOCKTAG::myLock, MyProc, PROCLOCKTAG::myProc, PGPROC::myProcLocks, LOCK::nGranted, LOCK::nRequested, NUM_LOCK_PARTITIONS, PANIC, PROCLOCK::procLink, PROCLOCK_PRINT, PROCLOCK::releaseMask, RemoveLocalLock(), START_CRIT_SECTION, LOCK::tag, PROCLOCK::tag, and TwoPhaseGetDummyProc().

Referenced by PrepareTransaction().

◆ RememberSimpleDeadLock()

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

Definition at line 1147 of file deadlock.c.

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

References deadlockDetails, fb(), DEADLOCK_INFO::lockmode, DEADLOCK_INFO::locktag, nDeadlockDetails, DEADLOCK_INFO::pid, and LOCK::tag.

Referenced by JoinWaitQueue().

◆ RemoveFromWaitQueue()

void RemoveFromWaitQueue ( PGPROC proc,
uint32  hashcode 
)
extern

Definition at line 2055 of file lock.c.

2056{
2057 LOCK *waitLock = proc->waitLock;
2058 PROCLOCK *proclock = proc->waitProcLock;
2059 LOCKMODE lockmode = proc->waitLockMode;
2061
2062 /* Make sure proc is waiting */
2065 Assert(waitLock);
2066 Assert(!dclist_is_empty(&waitLock->waitProcs));
2068
2069 /* Remove proc from lock's wait queue */
2071
2072 /* Undo increments of request counts by waiting process */
2073 Assert(waitLock->nRequested > 0);
2074 Assert(waitLock->nRequested > proc->waitLock->nGranted);
2075 waitLock->nRequested--;
2076 Assert(waitLock->requested[lockmode] > 0);
2077 waitLock->requested[lockmode]--;
2078 /* don't forget to clear waitMask bit if appropriate */
2079 if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
2080 waitLock->waitMask &= LOCKBIT_OFF(lockmode);
2081
2082 /* Clean up the proc's own state, and pass it the ok/fail signal */
2083 proc->waitLock = NULL;
2084 proc->waitProcLock = NULL;
2086
2087 /*
2088 * Delete the proclock immediately if it represents no already-held locks.
2089 * (This must happen now because if the owner of the lock decides to
2090 * release it, and the requested/granted counts then go to zero,
2091 * LockRelease expects there to be no remaining proclocks.) Then see if
2092 * any other waiters for the lock can be woken up now.
2093 */
2094 CleanUpLock(waitLock, proclock,
2095 LockMethods[lockmethodid], hashcode,
2096 true);
2097}
static bool dclist_is_empty(const dclist_head *head)
Definition ilist.h:682
static bool dlist_node_is_detached(const dlist_node *node)
Definition ilist.h:525
static void dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node)
Definition ilist.h:776
PROCLOCK * waitProcLock
Definition proc.h:306
dlist_node waitLink
Definition proc.h:305
ProcWaitStatus waitStatus
Definition proc.h:314

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

Referenced by CheckDeadLock(), and LockErrorCleanup().

◆ ResetAwaitedLock()

void ResetAwaitedLock ( void  )
extern

Definition at line 1916 of file lock.c.

1917{
1918 awaitedLock = NULL;
1919}

References awaitedLock, and fb().

Referenced by LockErrorCleanup().

◆ VirtualXactLock()

bool VirtualXactLock ( VirtualTransactionId  vxid,
bool  wait 
)
extern

Definition at line 4726 of file lock.c.

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

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

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

◆ VirtualXactLockTableCleanup()

void VirtualXactLockTableCleanup ( void  )
extern

Definition at line 4626 of file lock.c.

4627{
4628 bool fastpath;
4629 LocalTransactionId lxid;
4630
4632
4633 /*
4634 * Clean up shared memory state.
4635 */
4637
4638 fastpath = MyProc->fpVXIDLock;
4640 MyProc->fpVXIDLock = false;
4642
4644
4645 /*
4646 * If fpVXIDLock has been cleared without touching fpLocalTransactionId,
4647 * that means someone transferred the lock to the main lock table.
4648 */
4649 if (!fastpath && LocalTransactionIdIsValid(lxid))
4650 {
4652 LOCKTAG locktag;
4653
4654 vxid.procNumber = MyProcNumber;
4655 vxid.localTransactionId = lxid;
4656 SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid);
4657
4659 &locktag, ExclusiveLock, false);
4660 }
4661}
uint32 LocalTransactionId
Definition c.h:738
ProcNumber MyProcNumber
Definition globals.c:92
#define LocalTransactionIdIsValid(lxid)
Definition lock.h:69

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

Referenced by LockReleaseAll(), and ShutdownRecoveryTransactionEnvironment().

◆ VirtualXactLockTableInsert()

Variable Documentation

◆ log_lock_failures

PGDLLIMPORT bool log_lock_failures
extern

Definition at line 57 of file lock.c.

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

◆ max_locks_per_xact

PGDLLIMPORT int max_locks_per_xact
extern