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:806
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition lock.c:640
void lock_twophase_postabort(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4578
void PostPrepare_Locks(FullTransactionId fxid)
Definition lock.c:3580
void lock_twophase_standby_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4520
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
Definition lock.c:620
const LockMethodData * LockMethod
Definition lock.h:119
void VirtualXactLockTableInsert(VirtualTransactionId vxid)
Definition lock.c:4602
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
void GrantAwaitedLock(void)
Definition lock.c:1897
int LockWaiterCount(const LOCKTAG *locktag)
Definition lock.c:4836
void AtPrepare_Locks(void)
Definition lock.c:3484
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:2110
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition deadlock.c:1147
void InitLockManagerAccess(void)
Definition lock.c:502
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1666
void VirtualXactLockTableCleanup(void)
Definition lock.c:4625
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition lock.c:4725
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition lock.c:3077
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition lock.c:2054
LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
Definition lock.c:833
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition lock.c:2315
void ResetAwaitedLock(void)
Definition lock.c:1915
void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition lock.c:2714
void AbortStrongLockAcquire(void)
Definition lock.c:1868
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:3979
#define MAX_LOCKMODES
Definition lock.h:85
bool LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:693
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4235
void lock_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4552
void InitDeadLockChecking(void)
Definition deadlock.c:143
void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition lock.c:2619
LOCALLOCK * GetAwaitedLock(void)
Definition lock.c:1906
void LockReleaseSession(LOCKMETHODID lockmethodid)
Definition lock.c:2589
void MarkLockClear(LOCALLOCK *locallock)
Definition lock.c:1928
LockData * GetLockStatusData(void)
Definition lock.c:3776
DeadLockState DeadLockCheck(PGPROC *proc)
Definition deadlock.c:220
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:554
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition lock.c:1537
void lock_twophase_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4339
pg_noreturn void DeadLockReport(void)
Definition deadlock.c:1075
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition lock.c:524
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:4153
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
Definition lock.c:536
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 1868 of file lock.c.

1869{
1872
1873 if (locallock == NULL)
1874 return;
1875
1877 Assert(locallock->holdsStrongLockCount == true);
1881 locallock->holdsStrongLockCount = false;
1884}
#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 3484 of file lock.c.

3485{
3486 HASH_SEQ_STATUS status;
3488
3489 /* First, verify there aren't locks of both xact and session level */
3491
3492 /* Now do the per-locallock cleanup work */
3494
3495 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3496 {
3497 TwoPhaseLockRecord record;
3498 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3499 bool haveSessionLock;
3500 bool haveXactLock;
3501 int i;
3502
3503 /*
3504 * Ignore VXID locks. We don't want those to be held by prepared
3505 * transactions, since they aren't meaningful after a restart.
3506 */
3507 if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3508 continue;
3509
3510 /* Ignore it if we don't actually hold the lock */
3511 if (locallock->nLocks <= 0)
3512 continue;
3513
3514 /* Scan to see whether we hold it at session or transaction level */
3515 haveSessionLock = haveXactLock = false;
3516 for (i = locallock->numLockOwners - 1; i >= 0; i--)
3517 {
3518 if (lockOwners[i].owner == NULL)
3519 haveSessionLock = true;
3520 else
3521 haveXactLock = true;
3522 }
3523
3524 /* Ignore it if we have only session lock */
3525 if (!haveXactLock)
3526 continue;
3527
3528 /* This can't happen, because we already checked it */
3529 if (haveSessionLock)
3530 ereport(ERROR,
3532 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3533
3534 /*
3535 * If the local lock was taken via the fast-path, we need to move it
3536 * to the primary lock table, or just get a pointer to the existing
3537 * primary lock table entry if by chance it's already been
3538 * transferred.
3539 */
3540 if (locallock->proclock == NULL)
3541 {
3543 locallock->lock = locallock->proclock->tag.myLock;
3544 }
3545
3546 /*
3547 * Arrange to not release any strong lock count held by this lock
3548 * entry. We must retain the count until the prepared transaction is
3549 * committed or rolled back.
3550 */
3551 locallock->holdsStrongLockCount = false;
3552
3553 /*
3554 * Create a 2PC record.
3555 */
3556 memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3557 record.lockmode = locallock->tag.mode;
3558
3560 &record, sizeof(TwoPhaseLockRecord));
3561 }
3562}
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:875
#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:2966
static HTAB * LockMethodLocalHash
Definition lock.c:334
static void CheckForSessionAndXactLocks(void)
Definition lock.c:3396
@ 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:524
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:96
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:4235
#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 620 of file lock.c.

621{
623
624 if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
625 return true;
626
627 return false;
628}
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 1906 of file lock.c.

1907{
1908 return awaitedLock;
1909}
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 3979 of file lock.c.

3980{
3982 PGPROC *proc;
3983 int i;
3984
3986
3987 /*
3988 * Guess how much space we'll need, and preallocate. Most of the time
3989 * this will avoid needing to do repalloc while holding the LWLocks. (We
3990 * assume, but check with an Assert, that MaxBackends is enough entries
3991 * for the procs[] array; the other two could need enlargement, though.)
3992 */
3993 data->nprocs = data->nlocks = data->npids = 0;
3994 data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
3995 data->procs = palloc_array(BlockedProcData, data->maxprocs);
3996 data->locks = palloc_array(LockInstanceData, data->maxlocks);
3997 data->waiter_pids = palloc_array(int, data->maxpids);
3998
3999 /*
4000 * In order to search the ProcArray for blocked_pid and assume that that
4001 * entry won't immediately disappear under us, we must hold ProcArrayLock.
4002 * In addition, to examine the lock grouping fields of any other backend,
4003 * we must hold all the hash partition locks. (Only one of those locks is
4004 * actually relevant for any one lock group, but we can't know which one
4005 * ahead of time.) It's fairly annoying to hold all those locks
4006 * throughout this, but it's no worse than GetLockStatusData(), and it
4007 * does have the advantage that we're guaranteed to return a
4008 * self-consistent instantaneous state.
4009 */
4011
4013
4014 /* Nothing to do if it's gone */
4015 if (proc != NULL)
4016 {
4017 /*
4018 * Acquire lock on the entire shared lock data structure. See notes
4019 * in GetLockStatusData().
4020 */
4021 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
4023
4024 if (proc->lockGroupLeader == NULL)
4025 {
4026 /* Easy case, proc is not a lock group member */
4028 }
4029 else
4030 {
4031 /* Examine all procs in proc's lock group */
4032 dlist_iter iter;
4033
4035 {
4037
4038 memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
4040 }
4041 }
4042
4043 /*
4044 * And release locks. See notes in GetLockStatusData().
4045 */
4046 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
4048
4049 Assert(data->nprocs <= data->maxprocs);
4050 }
4051
4053
4054 return data;
4055}
#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:4059
#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 3077 of file lock.c.

3078{
3082 LOCK *lock;
3085 PROCLOCK *proclock;
3086 uint32 hashcode;
3088 int count = 0;
3089 int fast_count = 0;
3090
3092 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
3095 elog(ERROR, "unrecognized lock mode: %d", lockmode);
3096
3097 /*
3098 * Allocate memory to store results, and fill with InvalidVXID. We only
3099 * need enough space for MaxBackends + max_prepared_xacts + a terminator.
3100 * InHotStandby allocate once in TopMemoryContext.
3101 */
3102 if (InHotStandby)
3103 {
3104 if (vxids == NULL)
3107 sizeof(VirtualTransactionId) *
3109 }
3110 else
3112
3113 /* Compute hash code and partition lock, and look up conflicting modes. */
3114 hashcode = LockTagHashCode(locktag);
3116 conflictMask = lockMethodTable->conflictTab[lockmode];
3117
3118 /*
3119 * Fast path locks might not have been entered in the primary lock table.
3120 * If the lock we're dealing with could conflict with such a lock, we must
3121 * examine each backend's fast-path array for conflicts.
3122 */
3123 if (ConflictsWithRelationFastPath(locktag, lockmode))
3124 {
3125 int i;
3126 Oid relid = locktag->locktag_field2;
3128
3129 /* fast-path group the lock belongs to */
3130 uint32 group = FAST_PATH_REL_GROUP(relid);
3131
3132 /*
3133 * Iterate over relevant PGPROCs. Anything held by a prepared
3134 * transaction will have been transferred to the primary lock table,
3135 * so we need not worry about those. This is all a bit fuzzy, because
3136 * new locks could be taken after we've visited a particular
3137 * partition, but the callers had better be prepared to deal with that
3138 * anyway, since the locks could equally well be taken between the
3139 * time we return the value and the time the caller does something
3140 * with it.
3141 */
3142 for (i = 0; i < ProcGlobal->allProcCount; i++)
3143 {
3144 PGPROC *proc = GetPGProcByNumber(i);
3145 uint32 j;
3146
3147 /* A backend never blocks itself */
3148 if (proc == MyProc)
3149 continue;
3150
3152
3153 /*
3154 * If the target backend isn't referencing the same database as
3155 * the lock, then we needn't examine the individual relation IDs
3156 * at all; none of them can be relevant.
3157 *
3158 * See FastPathTransferRelationLocks() for discussion of why we do
3159 * this test after acquiring the lock.
3160 *
3161 * Also skip groups without any registered fast-path locks.
3162 */
3163 if (proc->databaseId != locktag->locktag_field1 ||
3164 proc->fpLockBits[group] == 0)
3165 {
3166 LWLockRelease(&proc->fpInfoLock);
3167 continue;
3168 }
3169
3170 for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++)
3171 {
3173
3174 /* index into the whole per-backend array */
3175 uint32 f = FAST_PATH_SLOT(group, j);
3176
3177 /* Look for an allocated slot matching the given relid. */
3178 if (relid != proc->fpRelId[f])
3179 continue;
3180 lockmask = FAST_PATH_GET_BITS(proc, f);
3181 if (!lockmask)
3182 continue;
3184
3185 /*
3186 * There can only be one entry per relation, so if we found it
3187 * and it doesn't conflict, we can skip the rest of the slots.
3188 */
3189 if ((lockmask & conflictMask) == 0)
3190 break;
3191
3192 /* Conflict! */
3193 GET_VXID_FROM_PGPROC(vxid, *proc);
3194
3196 vxids[count++] = vxid;
3197 /* else, xact already committed or aborted */
3198
3199 /* No need to examine remaining slots. */
3200 break;
3201 }
3202
3203 LWLockRelease(&proc->fpInfoLock);
3204 }
3205 }
3206
3207 /* Remember how many fast-path conflicts we found. */
3208 fast_count = count;
3209
3210 /*
3211 * Look up the lock object matching the tag.
3212 */
3214
3216 locktag,
3217 hashcode,
3218 HASH_FIND,
3219 NULL);
3220 if (!lock)
3221 {
3222 /*
3223 * If the lock object doesn't exist, there is nothing holding a lock
3224 * on this lockable object.
3225 */
3227 vxids[count].procNumber = INVALID_PROC_NUMBER;
3228 vxids[count].localTransactionId = InvalidLocalTransactionId;
3229 if (countp)
3230 *countp = count;
3231 return vxids;
3232 }
3233
3234 /*
3235 * Examine each existing holder (or awaiter) of the lock.
3236 */
3238 {
3239 proclock = dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
3240
3241 if (conflictMask & proclock->holdMask)
3242 {
3243 PGPROC *proc = proclock->tag.myProc;
3244
3245 /* A backend never blocks itself */
3246 if (proc != MyProc)
3247 {
3249
3250 GET_VXID_FROM_PGPROC(vxid, *proc);
3251
3253 {
3254 int i;
3255
3256 /* Avoid duplicate entries. */
3257 for (i = 0; i < fast_count; ++i)
3259 break;
3260 if (i >= fast_count)
3261 vxids[count++] = vxid;
3262 }
3263 /* else, xact already committed or aborted */
3264 }
3265 }
3266 }
3267
3269
3270 if (count > MaxBackends + max_prepared_xacts) /* should never happen */
3271 elog(PANIC, "too many conflicting locks found");
3272
3273 vxids[count].procNumber = INVALID_PROC_NUMBER;
3274 vxids[count].localTransactionId = InvalidLocalTransactionId;
3275 if (countp)
3276 *countp = count;
3277 return vxids;
3278}
#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:554
#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 524 of file lock.c.

525{
527
530}
#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 3776 of file lock.c.

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

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

1898{
1900}
static ResourceOwner awaitedOwner
Definition lock.c:340
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition lock.c:1800

References awaitedLock, awaitedOwner, and GrantLockLocal().

Referenced by LockErrorCleanup().

◆ GrantLock()

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

Definition at line 1666 of file lock.c.

1667{
1668 lock->nGranted++;
1669 lock->granted[lockmode]++;
1670 lock->grantMask |= LOCKBIT_ON(lockmode);
1671 if (lock->granted[lockmode] == lock->requested[lockmode])
1672 lock->waitMask &= LOCKBIT_OFF(lockmode);
1673 proclock->holdMask |= LOCKBIT_ON(lockmode);
1674 LOCK_PRINT("GrantLock", lock, lockmode);
1675 Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1676 Assert(lock->nGranted <= lock->nRequested);
1677}
#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 502 of file lock.c.

503{
504 /*
505 * Allocate non-shared hash table for LOCALLOCK structs. This stores lock
506 * counts and resource owner information.
507 */
508 HASHCTL info;
509
510 info.keysize = sizeof(LOCALLOCKTAG);
511 info.entrysize = sizeof(LOCALLOCK);
512
513 LockMethodLocalHash = hash_create("LOCALLOCK hash",
514 16,
515 &info,
517}
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 4578 of file lock.c.

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

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 4552 of file lock.c.

4554{
4556 PGPROC *proc = TwoPhaseGetDummyProc(fxid, true);
4557 LOCKTAG *locktag;
4560
4561 Assert(len == sizeof(TwoPhaseLockRecord));
4562 locktag = &rec->locktag;
4564
4566 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4568
4569 LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4570}
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition lock.c:3292
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 4339 of file lock.c.

4341{
4343 PGPROC *proc = TwoPhaseGetDummyProc(fxid, false);
4344 LOCKTAG *locktag;
4345 LOCKMODE lockmode;
4347 LOCK *lock;
4348 PROCLOCK *proclock;
4350 bool found;
4351 uint32 hashcode;
4353 int partition;
4356
4357 Assert(len == sizeof(TwoPhaseLockRecord));
4358 locktag = &rec->locktag;
4359 lockmode = rec->lockmode;
4361
4363 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4365
4366 hashcode = LockTagHashCode(locktag);
4367 partition = LockHashPartition(hashcode);
4369
4371
4372 /*
4373 * Find or create a lock with this tag.
4374 */
4376 locktag,
4377 hashcode,
4379 &found);
4380 if (!lock)
4381 {
4383 ereport(ERROR,
4385 errmsg("out of shared memory"),
4386 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4387 }
4388
4389 /*
4390 * if it's a new lock object, initialize it
4391 */
4392 if (!found)
4393 {
4394 lock->grantMask = 0;
4395 lock->waitMask = 0;
4396 dlist_init(&lock->procLocks);
4397 dclist_init(&lock->waitProcs);
4398 lock->nRequested = 0;
4399 lock->nGranted = 0;
4400 MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4401 MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4402 LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4403 }
4404 else
4405 {
4406 LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4407 Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4408 Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4409 Assert(lock->nGranted <= lock->nRequested);
4410 }
4411
4412 /*
4413 * Create the hash key for the proclock table.
4414 */
4415 proclocktag.myLock = lock;
4416 proclocktag.myProc = proc;
4417
4419
4420 /*
4421 * Find or create a proclock entry with this tag
4422 */
4424 &proclocktag,
4427 &found);
4428 if (!proclock)
4429 {
4430 /* Oops, not enough shmem for the proclock */
4431 if (lock->nRequested == 0)
4432 {
4433 /*
4434 * There are no other requestors of this lock, so garbage-collect
4435 * the lock object. We *must* do this to avoid a permanent leak
4436 * of shared memory, because there won't be anything to cause
4437 * anyone to release the lock object later.
4438 */
4441 &(lock->tag),
4442 hashcode,
4444 NULL))
4445 elog(PANIC, "lock table corrupted");
4446 }
4448 ereport(ERROR,
4450 errmsg("out of shared memory"),
4451 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4452 }
4453
4454 /*
4455 * If new, initialize the new entry
4456 */
4457 if (!found)
4458 {
4459 Assert(proc->lockGroupLeader == NULL);
4460 proclock->groupLeader = proc;
4461 proclock->holdMask = 0;
4462 proclock->releaseMask = 0;
4463 /* Add proclock to appropriate lists */
4464 dlist_push_tail(&lock->procLocks, &proclock->lockLink);
4466 &proclock->procLink);
4467 PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4468 }
4469 else
4470 {
4471 PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4472 Assert((proclock->holdMask & ~lock->grantMask) == 0);
4473 }
4474
4475 /*
4476 * lock->nRequested and lock->requested[] count the total number of
4477 * requests, whether granted or waiting, so increment those immediately.
4478 */
4479 lock->nRequested++;
4480 lock->requested[lockmode]++;
4481 Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4482
4483 /*
4484 * We shouldn't already hold the desired lock.
4485 */
4486 if (proclock->holdMask & LOCKBIT_ON(lockmode))
4487 elog(ERROR, "lock %s on object %u/%u/%u is already held",
4488 lockMethodTable->lockModeNames[lockmode],
4489 lock->tag.locktag_field1, lock->tag.locktag_field2,
4490 lock->tag.locktag_field3);
4491
4492 /*
4493 * We ignore any possible conflicts and just grant ourselves the lock. Not
4494 * only because we don't bother, but also to avoid deadlocks when
4495 * switching from standby to normal mode. See function comment.
4496 */
4497 GrantLock(lock, proclock, lockmode);
4498
4499 /*
4500 * Bump strong lock count, to make sure any fast-path lock requests won't
4501 * be granted without consulting the primary lock table.
4502 */
4503 if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4504 {
4506
4510 }
4511
4513}
#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:602
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1666
#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 4520 of file lock.c.

4522{
4524 LOCKTAG *locktag;
4525 LOCKMODE lockmode;
4527
4528 Assert(len == sizeof(TwoPhaseLockRecord));
4529 locktag = &rec->locktag;
4530 lockmode = rec->lockmode;
4532
4534 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4535
4536 if (lockmode == AccessExclusiveLock &&
4537 locktag->locktag_type == LOCKTAG_RELATION)
4538 {
4540 locktag->locktag_field1 /* dboid */ ,
4541 locktag->locktag_field2 /* reloid */ );
4542 }
4543}
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 833 of file lock.c.

840{
845 LOCK *lock;
846 PROCLOCK *proclock;
847 bool found;
848 ResourceOwner owner;
849 uint32 hashcode;
851 bool found_conflict;
853 bool log_lock = false;
854
856 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
859 elog(ERROR, "unrecognized lock mode: %d", lockmode);
860
861 if (RecoveryInProgress() && !InRecovery &&
862 (locktag->locktag_type == LOCKTAG_OBJECT ||
863 locktag->locktag_type == LOCKTAG_RELATION) &&
864 lockmode > RowExclusiveLock)
867 errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
868 lockMethodTable->lockModeNames[lockmode]),
869 errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
870
871#ifdef LOCK_DEBUG
872 if (LOCK_DEBUG_ENABLED(locktag))
873 elog(LOG, "LockAcquire: lock [%u,%u] %s",
874 locktag->locktag_field1, locktag->locktag_field2,
875 lockMethodTable->lockModeNames[lockmode]);
876#endif
877
878 /* Identify owner for lock */
879 if (sessionLock)
880 owner = NULL;
881 else
882 owner = CurrentResourceOwner;
883
884 /*
885 * Find or create a LOCALLOCK entry for this lock and lockmode
886 */
887 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
888 localtag.lock = *locktag;
889 localtag.mode = lockmode;
890
892 &localtag,
893 HASH_ENTER, &found);
894
895 /*
896 * if it's a new locallock object, initialize it
897 */
898 if (!found)
899 {
900 locallock->lock = NULL;
901 locallock->proclock = NULL;
902 locallock->hashcode = LockTagHashCode(&(localtag.lock));
903 locallock->nLocks = 0;
904 locallock->holdsStrongLockCount = false;
905 locallock->lockCleared = false;
906 locallock->numLockOwners = 0;
907 locallock->maxLockOwners = 8;
908 locallock->lockOwners = NULL; /* in case next line fails */
909 locallock->lockOwners = (LOCALLOCKOWNER *)
911 locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
912 }
913 else
914 {
915 /* Make sure there will be room to remember the lock */
916 if (locallock->numLockOwners >= locallock->maxLockOwners)
917 {
918 int newsize = locallock->maxLockOwners * 2;
919
920 locallock->lockOwners = (LOCALLOCKOWNER *)
921 repalloc(locallock->lockOwners,
922 newsize * sizeof(LOCALLOCKOWNER));
923 locallock->maxLockOwners = newsize;
924 }
925 }
926 hashcode = locallock->hashcode;
927
928 if (locallockp)
930
931 /*
932 * If we already hold the lock, we can just increase the count locally.
933 *
934 * If lockCleared is already set, caller need not worry about absorbing
935 * sinval messages related to the lock's object.
936 */
937 if (locallock->nLocks > 0)
938 {
940 if (locallock->lockCleared)
942 else
944 }
945
946 /*
947 * We don't acquire any other heavyweight lock while holding the relation
948 * extension lock. We do allow to acquire the same relation extension
949 * lock more than once but that case won't reach here.
950 */
952
953 /*
954 * Prepare to emit a WAL record if acquisition of this lock needs to be
955 * replayed in a standby server.
956 *
957 * Here we prepare to log; after lock is acquired we'll issue log record.
958 * This arrangement simplifies error recovery in case the preparation step
959 * fails.
960 *
961 * Only AccessExclusiveLocks can conflict with lock types that read-only
962 * transactions can acquire in a standby server. Make sure this definition
963 * matches the one in GetRunningTransactionLocks().
964 */
965 if (lockmode >= AccessExclusiveLock &&
966 locktag->locktag_type == LOCKTAG_RELATION &&
969 {
971 log_lock = true;
972 }
973
974 /*
975 * Attempt to take lock via fast path, if eligible. But if we remember
976 * having filled up the fast path array, we don't attempt to make any
977 * further use of it until we release some locks. It's possible that some
978 * other backend has transferred some of those locks to the shared hash
979 * table, leaving space free, but it's not worth acquiring the LWLock just
980 * to check. It's also possible that we're acquiring a second or third
981 * lock type on a relation we have already locked using the fast-path, but
982 * for now we don't worry about that case either.
983 */
984 if (EligibleForRelationFastPath(locktag, lockmode))
985 {
988 {
990 bool acquired;
991
992 /*
993 * LWLockAcquire acts as a memory sequencing point, so it's safe
994 * to assume that any strong locker whose increment to
995 * FastPathStrongRelationLocks->counts becomes visible after we
996 * test it has yet to begin to transfer fast-path locks.
997 */
1000 acquired = false;
1001 else
1003 lockmode);
1005 if (acquired)
1006 {
1007 /*
1008 * The locallock might contain stale pointers to some old
1009 * shared objects; we MUST reset these to null before
1010 * considering the lock to be acquired via fast-path.
1011 */
1012 locallock->lock = NULL;
1013 locallock->proclock = NULL;
1014 GrantLockLocal(locallock, owner);
1015 return LOCKACQUIRE_OK;
1016 }
1017 }
1018 else
1019 {
1020 /*
1021 * Increment the lock statistics counter if lock could not be
1022 * acquired via the fast-path.
1023 */
1024 pgstat_count_lock_fastpath_exceeded(locallock->tag.lock.locktag_type);
1025 }
1026 }
1027
1028 /*
1029 * If this lock could potentially have been taken via the fast-path by
1030 * some other backend, we must (temporarily) disable further use of the
1031 * fast-path for this lock tag, and migrate any locks already taken via
1032 * this method to the main lock table.
1033 */
1034 if (ConflictsWithRelationFastPath(locktag, lockmode))
1035 {
1037
1040 hashcode))
1041 {
1043 if (locallock->nLocks == 0)
1045 if (locallockp)
1046 *locallockp = NULL;
1048 ereport(ERROR,
1050 errmsg("out of shared memory"),
1051 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
1052 else
1053 return LOCKACQUIRE_NOT_AVAIL;
1054 }
1055 }
1056
1057 /*
1058 * We didn't find the lock in our LOCALLOCK table, and we didn't manage to
1059 * take it via the fast-path, either, so we've got to mess with the shared
1060 * lock table.
1061 */
1063
1065
1066 /*
1067 * Find or create lock and proclock entries with this tag
1068 *
1069 * Note: if the locallock object already existed, it might have a pointer
1070 * to the lock already ... but we should not assume that that pointer is
1071 * valid, since a lock object with zero hold and request counts can go
1072 * away anytime. So we have to use SetupLockInTable() to recompute the
1073 * lock and proclock pointers, even if they're already set.
1074 */
1075 proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
1076 hashcode, lockmode);
1077 if (!proclock)
1078 {
1081 if (locallock->nLocks == 0)
1083 if (locallockp)
1084 *locallockp = NULL;
1086 ereport(ERROR,
1088 errmsg("out of shared memory"),
1089 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
1090 else
1091 return LOCKACQUIRE_NOT_AVAIL;
1092 }
1093 locallock->proclock = proclock;
1094 lock = proclock->tag.myLock;
1095 locallock->lock = lock;
1096
1097 /*
1098 * If lock requested conflicts with locks requested by waiters, must join
1099 * wait queue. Otherwise, check for conflict with already-held locks.
1100 * (That's last because most complex check.)
1101 */
1102 if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
1103 found_conflict = true;
1104 else
1106 lock, proclock);
1107
1108 if (!found_conflict)
1109 {
1110 /* No conflict with held or previously requested locks */
1111 GrantLock(lock, proclock, lockmode);
1113 }
1114 else
1115 {
1116 /*
1117 * Join the lock's wait queue. We call this even in the dontWait
1118 * case, because JoinWaitQueue() may discover that we can acquire the
1119 * lock immediately after all.
1120 */
1122 }
1123
1125 {
1126 /*
1127 * We're not getting the lock because a deadlock was detected already
1128 * while trying to join the wait queue, or because we would have to
1129 * wait but the caller requested no blocking.
1130 *
1131 * Undo the changes to shared entries before releasing the partition
1132 * lock.
1133 */
1135
1136 if (proclock->holdMask == 0)
1137 {
1139
1141 hashcode);
1142 dlist_delete(&proclock->lockLink);
1143 dlist_delete(&proclock->procLink);
1145 &(proclock->tag),
1148 NULL))
1149 elog(PANIC, "proclock table corrupted");
1150 }
1151 else
1152 PROCLOCK_PRINT("LockAcquire: did not join wait queue", proclock);
1153 lock->nRequested--;
1154 lock->requested[lockmode]--;
1155 LOCK_PRINT("LockAcquire: did not join wait queue",
1156 lock, lockmode);
1157 Assert((lock->nRequested > 0) &&
1158 (lock->requested[lockmode] >= 0));
1159 Assert(lock->nGranted <= lock->nRequested);
1161 if (locallock->nLocks == 0)
1163
1164 if (dontWait)
1165 {
1166 /*
1167 * Log lock holders and waiters as a detail log message if
1168 * logLockFailure = true and lock acquisition fails with dontWait
1169 * = true
1170 */
1171 if (logLockFailure)
1172 {
1176 const char *modename;
1177 int lockHoldersNum = 0;
1178
1182
1183 DescribeLockTag(&buf, &locallock->tag.lock);
1184 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
1185 lockmode);
1186
1187 /* Gather a list of all lock holders and waiters */
1192
1193 ereport(LOG,
1194 (errmsg("process %d could not obtain %s on %s",
1195 MyProcPid, modename, buf.data),
1197 "Process holding the lock: %s, Wait queue: %s.",
1198 "Processes holding the lock: %s, Wait queue: %s.",
1200 lock_holders_sbuf.data,
1201 lock_waiters_sbuf.data)));
1202
1203 pfree(buf.data);
1206 }
1207 if (locallockp)
1208 *locallockp = NULL;
1209 return LOCKACQUIRE_NOT_AVAIL;
1210 }
1211 else
1212 {
1214 /* DeadLockReport() will not return */
1215 }
1216 }
1217
1218 /*
1219 * We are now in the lock queue, or the lock was already granted. If
1220 * queued, go to sleep.
1221 */
1223 {
1224 Assert(!dontWait);
1225 PROCLOCK_PRINT("LockAcquire: sleeping on lock", proclock);
1226 LOCK_PRINT("LockAcquire: sleeping on lock", lock, lockmode);
1228
1230
1231 /*
1232 * NOTE: do not do any material change of state between here and
1233 * return. All required changes in locktable state must have been
1234 * done when the lock was granted to us --- see notes in WaitOnLock.
1235 */
1236
1238 {
1239 /*
1240 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
1241 * now.
1242 */
1243 Assert(!dontWait);
1245 /* DeadLockReport() will not return */
1246 }
1247 }
1248 else
1251
1252 /* The lock was granted to us. Update the local lock entry accordingly */
1253 Assert((proclock->holdMask & LOCKBIT_ON(lockmode)) != 0);
1254 GrantLockLocal(locallock, owner);
1255
1256 /*
1257 * Lock state is fully up-to-date now; if we error out after this, no
1258 * special error cleanup is required.
1259 */
1261
1262 /*
1263 * Emit a WAL record if acquisition of this lock needs to be replayed in a
1264 * standby server.
1265 */
1266 if (log_lock)
1267 {
1268 /*
1269 * Decode the locktag back to the original values, to avoid sending
1270 * lots of empty bytes with every message. See lock.h to check how a
1271 * locktag is defined for LOCKTAG_RELATION
1272 */
1274 locktag->locktag_field2);
1275 }
1276
1277 return LOCKACQUIRE_OK;
1278}
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:1484
static PROCLOCK * SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc, const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
Definition lock.c:1291
static bool FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag, uint32 hashcode)
Definition lock.c:2869
void AbortStrongLockAcquire(void)
Definition lock.c:1868
static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
Definition lock.c:2790
static int FastPathLocalUseCounts[FP_LOCK_GROUPS_PER_BACKEND_MAX]
Definition lock.c:179
static ProcWaitStatus WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
Definition lock.c:1940
#define EligibleForRelationFastPath(locktag, mode)
Definition lock.c:270
static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode)
Definition lock.c:1832
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition lock.c:1537
static void FinishStrongLockAcquire(void)
Definition lock.c:1858
#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:6836
#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 1537 of file lock.c.

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

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

642{
645
646 /*
647 * See if there is a LOCALLOCK entry for this lock and lockmode
648 */
649 MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
650 localtag.lock = *locktag;
651 localtag.mode = lockmode;
652
654 &localtag,
655 HASH_FIND, NULL);
656
657 if (locallock && locallock->nLocks > 0)
658 return true;
659
660 if (orstronger)
661 {
663
664 for (slockmode = lockmode + 1;
666 slockmode++)
667 {
668 if (LockHeldByMe(locktag, slockmode, false))
669 return true;
670 }
671 }
672
673 return false;
674}
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition lock.c:640
#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 2714 of file lock.c.

2715{
2717
2718 Assert(parent != NULL);
2719
2720 if (locallocks == NULL)
2721 {
2722 HASH_SEQ_STATUS status;
2724
2726
2727 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2729 }
2730 else
2731 {
2732 int i;
2733
2734 for (i = nlocks - 1; i >= 0; i--)
2735 LockReassignOwner(locallocks[i], parent);
2736 }
2737}
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition lock.c:2744
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 2110 of file lock.c.

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

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

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

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

Referenced by ResourceOwnerReleaseInternal().

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)
extern

Definition at line 2589 of file lock.c.

2590{
2591 HASH_SEQ_STATUS status;
2593
2595 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2596
2598
2599 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2600 {
2601 /* Ignore items that are not of the specified lock method */
2603 continue;
2604
2606 }
2607}

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 554 of file lock.c.

555{
556 return get_hash_value(LockMethodLockHash, locktag);
557}
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 4836 of file lock.c.

4837{
4839 LOCK *lock;
4840 bool found;
4841 uint32 hashcode;
4843 int waiters = 0;
4844
4846 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4847
4848 hashcode = LockTagHashCode(locktag);
4851
4853 locktag,
4854 hashcode,
4855 HASH_FIND,
4856 &found);
4857 if (found)
4858 {
4859 Assert(lock != NULL);
4860 waiters = lock->nRequested;
4861 }
4863
4864 return waiters;
4865}

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 1928 of file lock.c.

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

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 3580 of file lock.c.

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

2055{
2056 LOCK *waitLock = proc->waitLock;
2057 PROCLOCK *proclock = proc->waitProcLock;
2058 LOCKMODE lockmode = proc->waitLockMode;
2060
2061 /* Make sure proc is waiting */
2064 Assert(waitLock);
2065 Assert(!dclist_is_empty(&waitLock->waitProcs));
2067
2068 /* Remove proc from lock's wait queue */
2070
2071 /* Undo increments of request counts by waiting process */
2072 Assert(waitLock->nRequested > 0);
2073 Assert(waitLock->nRequested > proc->waitLock->nGranted);
2074 waitLock->nRequested--;
2075 Assert(waitLock->requested[lockmode] > 0);
2076 waitLock->requested[lockmode]--;
2077 /* don't forget to clear waitMask bit if appropriate */
2078 if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
2079 waitLock->waitMask &= LOCKBIT_OFF(lockmode);
2080
2081 /* Clean up the proc's own state, and pass it the ok/fail signal */
2082 proc->waitLock = NULL;
2083 proc->waitProcLock = NULL;
2085
2086 /*
2087 * Delete the proclock immediately if it represents no already-held locks.
2088 * (This must happen now because if the owner of the lock decides to
2089 * release it, and the requested/granted counts then go to zero,
2090 * LockRelease expects there to be no remaining proclocks.) Then see if
2091 * any other waiters for the lock can be woken up now.
2092 */
2093 CleanUpLock(waitLock, proclock,
2094 LockMethods[lockmethodid], hashcode,
2095 true);
2096}
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 1915 of file lock.c.

1916{
1917 awaitedLock = NULL;
1918}

References awaitedLock, and fb().

Referenced by LockErrorCleanup().

◆ VirtualXactLock()

bool VirtualXactLock ( VirtualTransactionId  vxid,
bool  wait 
)
extern

Definition at line 4725 of file lock.c.

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

4626{
4627 bool fastpath;
4628 LocalTransactionId lxid;
4629
4631
4632 /*
4633 * Clean up shared memory state.
4634 */
4636
4637 fastpath = MyProc->fpVXIDLock;
4639 MyProc->fpVXIDLock = false;
4641
4643
4644 /*
4645 * If fpVXIDLock has been cleared without touching fpLocalTransactionId,
4646 * that means someone transferred the lock to the main lock table.
4647 */
4648 if (!fastpath && LocalTransactionIdIsValid(lxid))
4649 {
4651 LOCKTAG locktag;
4652
4653 vxid.procNumber = MyProcNumber;
4654 vxid.localTransactionId = lxid;
4655 SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid);
4656
4658 &locktag, ExclusiveLock, false);
4659 }
4660}
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