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 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 LockManagerShmemInit (void)
 
Size LockManagerShmemSize (void)
 
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 LockManagerShmemInit(void);
378extern Size LockManagerShmemSize(void);
379extern void InitLockManagerAccess(void);
380extern LockMethod GetLocksMethodTable(const LOCK *lock);
381extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag);
382extern uint32 LockTagHashCode(const LOCKTAG *locktag);
384extern LockAcquireResult LockAcquire(const LOCKTAG *locktag,
385 LOCKMODE lockmode,
386 bool sessionLock,
387 bool dontWait);
388extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag,
389 LOCKMODE lockmode,
390 bool sessionLock,
391 bool dontWait,
394 bool logLockFailure);
395extern void AbortStrongLockAcquire(void);
396extern void MarkLockClear(LOCALLOCK *locallock);
397extern bool LockRelease(const LOCKTAG *locktag,
398 LOCKMODE lockmode, bool sessionLock);
401extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks);
402extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks);
403extern bool LockHeldByMe(const LOCKTAG *locktag,
404 LOCKMODE lockmode, bool orstronger);
405#ifdef USE_ASSERT_CHECKING
406extern HTAB *GetLockMethodLocalHash(void);
407#endif
408extern bool LockHasWaiters(const LOCKTAG *locktag,
409 LOCKMODE lockmode, bool sessionLock);
410extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
411 LOCKMODE lockmode, int *countp);
412extern void AtPrepare_Locks(void);
413extern void PostPrepare_Locks(FullTransactionId fxid);
415 LOCKMODE lockmode,
416 LOCK *lock, PROCLOCK *proclock);
417extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
418extern void GrantAwaitedLock(void);
419extern LOCALLOCK *GetAwaitedLock(void);
420extern void ResetAwaitedLock(void);
421
422extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode);
423extern LockData *GetLockStatusData(void);
425
428
429extern void lock_twophase_recover(FullTransactionId fxid, uint16 info,
430 void *recdata, uint32 len);
432 void *recdata, uint32 len);
434 void *recdata, uint32 len);
436 void *recdata, uint32 len);
437
440pg_noreturn extern void DeadLockReport(void);
442 LOCKMODE lockmode,
443 LOCK *lock,
444 PGPROC *proc2);
445extern void InitDeadLockChecking(void);
446
447extern int LockWaiterCount(const LOCKTAG *locktag);
448
449#ifdef LOCK_DEBUG
450extern void DumpLocks(PGPROC *proc);
451extern void DumpAllLocks(void);
452#endif
453
454/* Lock a VXID (used to wait for a transaction to finish) */
456extern void VirtualXactLockTableCleanup(void);
457extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait);
458
459#endif /* LOCK_H_ */
#define pg_noreturn
Definition c.h:184
int64_t int64
Definition c.h:615
uint16_t uint16
Definition c.h:617
uint32_t uint32
Definition c.h:618
size_t Size
Definition c.h:691
int64 TimestampTz
Definition timestamp.h:39
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition lock.c:809
bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode, bool orstronger)
Definition lock.c:643
void lock_twophase_postabort(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4595
void PostPrepare_Locks(FullTransactionId fxid)
Definition lock.c:3572
void lock_twophase_standby_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4537
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
Definition lock.c:623
const LockMethodData * LockMethod
Definition lock.h:119
void VirtualXactLockTableInsert(VirtualTransactionId vxid)
Definition lock.c:4619
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
void GrantAwaitedLock(void)
Definition lock.c:1889
int LockWaiterCount(const LOCKTAG *locktag)
Definition lock.c:4853
void AtPrepare_Locks(void)
Definition lock.c:3476
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:2102
Size LockManagerShmemSize(void)
Definition lock.c:3756
void RememberSimpleDeadLock(PGPROC *proc1, LOCKMODE lockmode, LOCK *lock, PGPROC *proc2)
Definition deadlock.c:1147
void InitLockManagerAccess(void)
Definition lock.c:505
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1658
void VirtualXactLockTableCleanup(void)
Definition lock.c:4642
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition lock.c:4742
VirtualTransactionId * GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
Definition lock.c:3069
void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
Definition lock.c:2046
LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait, bool reportMemoryError, LOCALLOCK **locallockp, bool logLockFailure)
Definition lock.c:836
void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
Definition lock.c:2307
void ResetAwaitedLock(void)
Definition lock.c:1907
void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition lock.c:2706
void AbortStrongLockAcquire(void)
Definition lock.c:1860
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:3996
#define MAX_LOCKMODES
Definition lock.h:85
void LockManagerShmemInit(void)
Definition lock.c:444
bool LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:696
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4252
void lock_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4569
void InitDeadLockChecking(void)
Definition deadlock.c:143
void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
Definition lock.c:2611
LOCALLOCK * GetAwaitedLock(void)
Definition lock.c:1898
void LockReleaseSession(LOCKMETHODID lockmethodid)
Definition lock.c:2581
void MarkLockClear(LOCALLOCK *locallock)
Definition lock.c:1920
LockData * GetLockStatusData(void)
Definition lock.c:3793
DeadLockState DeadLockCheck(PGPROC *proc)
Definition deadlock.c:220
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:557
bool LockCheckConflicts(LockMethod lockMethodTable, LOCKMODE lockmode, LOCK *lock, PROCLOCK *proclock)
Definition lock.c:1529
void lock_twophase_recover(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4356
pg_noreturn void DeadLockReport(void)
Definition deadlock.c:1075
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition lock.c:527
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:4170
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
Definition lock.c:539
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:176
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:162
#define LOCK_MANAGER_LWLOCK_OFFSET
Definition lwlock.h:103
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

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

1861{
1864
1865 if (locallock == NULL)
1866 return;
1867
1869 Assert(locallock->holdsStrongLockCount == true);
1873 locallock->holdsStrongLockCount = false;
1876}
#define Assert(condition)
Definition c.h:945
#define FastPathStrongLockHashPartition(hashcode)
Definition lock.c:303
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition lock.c:312
static LOCALLOCK * StrongLockInProgress
Definition lock.c:327
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:309

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

3477{
3478 HASH_SEQ_STATUS status;
3480
3481 /* First, verify there aren't locks of both xact and session level */
3483
3484 /* Now do the per-locallock cleanup work */
3486
3487 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3488 {
3489 TwoPhaseLockRecord record;
3490 LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3491 bool haveSessionLock;
3492 bool haveXactLock;
3493 int i;
3494
3495 /*
3496 * Ignore VXID locks. We don't want those to be held by prepared
3497 * transactions, since they aren't meaningful after a restart.
3498 */
3499 if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3500 continue;
3501
3502 /* Ignore it if we don't actually hold the lock */
3503 if (locallock->nLocks <= 0)
3504 continue;
3505
3506 /* Scan to see whether we hold it at session or transaction level */
3507 haveSessionLock = haveXactLock = false;
3508 for (i = locallock->numLockOwners - 1; i >= 0; i--)
3509 {
3510 if (lockOwners[i].owner == NULL)
3511 haveSessionLock = true;
3512 else
3513 haveXactLock = true;
3514 }
3515
3516 /* Ignore it if we have only session lock */
3517 if (!haveXactLock)
3518 continue;
3519
3520 /* This can't happen, because we already checked it */
3521 if (haveSessionLock)
3522 ereport(ERROR,
3524 errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3525
3526 /*
3527 * If the local lock was taken via the fast-path, we need to move it
3528 * to the primary lock table, or just get a pointer to the existing
3529 * primary lock table entry if by chance it's already been
3530 * transferred.
3531 */
3532 if (locallock->proclock == NULL)
3533 {
3535 locallock->lock = locallock->proclock->tag.myLock;
3536 }
3537
3538 /*
3539 * Arrange to not release any strong lock count held by this lock
3540 * entry. We must retain the count until the prepared transaction is
3541 * committed or rolled back.
3542 */
3543 locallock->holdsStrongLockCount = false;
3544
3545 /*
3546 * Create a 2PC record.
3547 */
3548 memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3549 record.lockmode = locallock->tag.mode;
3550
3552 &record, sizeof(TwoPhaseLockRecord));
3553 }
3554}
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition dynahash.c:1415
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition dynahash.c:1380
int errcode(int sqlerrcode)
Definition elog.c:874
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
int i
Definition isn.c:77
static PROCLOCK * FastPathGetRelationLockEntry(LOCALLOCK *locallock)
Definition lock.c:2958
static HTAB * LockMethodLocalHash
Definition lock.c:323
static void CheckForSessionAndXactLocks(void)
Definition lock.c:3388
@ LOCKTAG_VIRTUALTRANSACTION
Definition locktag.h:43
static char * errmsg
LOCKTAG locktag
Definition lock.c:160
LOCKMODE lockmode
Definition lock.c:161
void RegisterTwoPhaseRecord(TwoPhaseRmgrId rmid, uint16 info, const void *data, uint32 len)
Definition twophase.c:1274
#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, 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:41
#define elog(elevel,...)
Definition elog.h:226
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:527
void ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
Definition proc.c:1752
PGPROC ** procs
Definition deadlock.c:60
LOCK * lock
Definition deadlock.c:59
int nProcs
Definition deadlock.c:61

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

Referenced by CheckDeadLock().

◆ DeadLockReport()

pg_noreturn void DeadLockReport ( void  )
extern

Definition at line 1075 of file deadlock.c.

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

624{
626
627 if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
628 return true;
629
630 return false;
631}
static const LockMethod LockMethods[]
Definition lock.c:150
#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 1898 of file lock.c.

1899{
1900 return awaitedLock;
1901}
static LOCALLOCK * awaitedLock
Definition lock.c:328

References awaitedLock.

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

◆ GetBlockerStatusData()

BlockedProcsData * GetBlockerStatusData ( int  blocked_pid)
extern

Definition at line 3996 of file lock.c.

3997{
3999 PGPROC *proc;
4000 int i;
4001
4003
4004 /*
4005 * Guess how much space we'll need, and preallocate. Most of the time
4006 * this will avoid needing to do repalloc while holding the LWLocks. (We
4007 * assume, but check with an Assert, that MaxBackends is enough entries
4008 * for the procs[] array; the other two could need enlargement, though.)
4009 */
4010 data->nprocs = data->nlocks = data->npids = 0;
4011 data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
4012 data->procs = palloc_array(BlockedProcData, data->maxprocs);
4013 data->locks = palloc_array(LockInstanceData, data->maxlocks);
4014 data->waiter_pids = palloc_array(int, data->maxpids);
4015
4016 /*
4017 * In order to search the ProcArray for blocked_pid and assume that that
4018 * entry won't immediately disappear under us, we must hold ProcArrayLock.
4019 * In addition, to examine the lock grouping fields of any other backend,
4020 * we must hold all the hash partition locks. (Only one of those locks is
4021 * actually relevant for any one lock group, but we can't know which one
4022 * ahead of time.) It's fairly annoying to hold all those locks
4023 * throughout this, but it's no worse than GetLockStatusData(), and it
4024 * does have the advantage that we're guaranteed to return a
4025 * self-consistent instantaneous state.
4026 */
4028
4030
4031 /* Nothing to do if it's gone */
4032 if (proc != NULL)
4033 {
4034 /*
4035 * Acquire lock on the entire shared lock data structure. See notes
4036 * in GetLockStatusData().
4037 */
4038 for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
4040
4041 if (proc->lockGroupLeader == NULL)
4042 {
4043 /* Easy case, proc is not a lock group member */
4045 }
4046 else
4047 {
4048 /* Examine all procs in proc's lock group */
4049 dlist_iter iter;
4050
4052 {
4054
4055 memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
4057 }
4058 }
4059
4060 /*
4061 * And release locks. See notes in GetLockStatusData().
4062 */
4063 for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
4065
4066 Assert(data->nprocs <= data->maxprocs);
4067 }
4068
4070
4071 return data;
4072}
#define palloc_object(type)
Definition fe_memutils.h:74
#define palloc_array(type, count)
Definition fe_memutils.h:76
int MaxBackends
Definition globals.c:146
#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:4076
#define LockHashPartitionLockByIndex(i)
Definition lock.h:360
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794
#define NUM_LOCK_PARTITIONS
Definition lwlock.h:95
@ LW_SHARED
Definition lwlock.h:113
const void * data
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3179
dlist_head lockGroupMembers
Definition proc.h:296
PGPROC * lockGroupLeader
Definition proc.h:295
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 3069 of file lock.c.

3070{
3074 LOCK *lock;
3077 PROCLOCK *proclock;
3078 uint32 hashcode;
3080 int count = 0;
3081 int fast_count = 0;
3082
3084 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
3087 elog(ERROR, "unrecognized lock mode: %d", lockmode);
3088
3089 /*
3090 * Allocate memory to store results, and fill with InvalidVXID. We only
3091 * need enough space for MaxBackends + max_prepared_xacts + a terminator.
3092 * InHotStandby allocate once in TopMemoryContext.
3093 */
3094 if (InHotStandby)
3095 {
3096 if (vxids == NULL)
3099 sizeof(VirtualTransactionId) *
3101 }
3102 else
3104
3105 /* Compute hash code and partition lock, and look up conflicting modes. */
3106 hashcode = LockTagHashCode(locktag);
3108 conflictMask = lockMethodTable->conflictTab[lockmode];
3109
3110 /*
3111 * Fast path locks might not have been entered in the primary lock table.
3112 * If the lock we're dealing with could conflict with such a lock, we must
3113 * examine each backend's fast-path array for conflicts.
3114 */
3115 if (ConflictsWithRelationFastPath(locktag, lockmode))
3116 {
3117 int i;
3118 Oid relid = locktag->locktag_field2;
3120
3121 /* fast-path group the lock belongs to */
3122 uint32 group = FAST_PATH_REL_GROUP(relid);
3123
3124 /*
3125 * Iterate over relevant PGPROCs. Anything held by a prepared
3126 * transaction will have been transferred to the primary lock table,
3127 * so we need not worry about those. This is all a bit fuzzy, because
3128 * new locks could be taken after we've visited a particular
3129 * partition, but the callers had better be prepared to deal with that
3130 * anyway, since the locks could equally well be taken between the
3131 * time we return the value and the time the caller does something
3132 * with it.
3133 */
3134 for (i = 0; i < ProcGlobal->allProcCount; i++)
3135 {
3136 PGPROC *proc = GetPGProcByNumber(i);
3137 uint32 j;
3138
3139 /* A backend never blocks itself */
3140 if (proc == MyProc)
3141 continue;
3142
3144
3145 /*
3146 * If the target backend isn't referencing the same database as
3147 * the lock, then we needn't examine the individual relation IDs
3148 * at all; none of them can be relevant.
3149 *
3150 * See FastPathTransferRelationLocks() for discussion of why we do
3151 * this test after acquiring the lock.
3152 *
3153 * Also skip groups without any registered fast-path locks.
3154 */
3155 if (proc->databaseId != locktag->locktag_field1 ||
3156 proc->fpLockBits[group] == 0)
3157 {
3158 LWLockRelease(&proc->fpInfoLock);
3159 continue;
3160 }
3161
3162 for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++)
3163 {
3165
3166 /* index into the whole per-backend array */
3167 uint32 f = FAST_PATH_SLOT(group, j);
3168
3169 /* Look for an allocated slot matching the given relid. */
3170 if (relid != proc->fpRelId[f])
3171 continue;
3172 lockmask = FAST_PATH_GET_BITS(proc, f);
3173 if (!lockmask)
3174 continue;
3176
3177 /*
3178 * There can only be one entry per relation, so if we found it
3179 * and it doesn't conflict, we can skip the rest of the slots.
3180 */
3181 if ((lockmask & conflictMask) == 0)
3182 break;
3183
3184 /* Conflict! */
3185 GET_VXID_FROM_PGPROC(vxid, *proc);
3186
3188 vxids[count++] = vxid;
3189 /* else, xact already committed or aborted */
3190
3191 /* No need to examine remaining slots. */
3192 break;
3193 }
3194
3195 LWLockRelease(&proc->fpInfoLock);
3196 }
3197 }
3198
3199 /* Remember how many fast-path conflicts we found. */
3200 fast_count = count;
3201
3202 /*
3203 * Look up the lock object matching the tag.
3204 */
3206
3208 locktag,
3209 hashcode,
3210 HASH_FIND,
3211 NULL);
3212 if (!lock)
3213 {
3214 /*
3215 * If the lock object doesn't exist, there is nothing holding a lock
3216 * on this lockable object.
3217 */
3219 vxids[count].procNumber = INVALID_PROC_NUMBER;
3220 vxids[count].localTransactionId = InvalidLocalTransactionId;
3221 if (countp)
3222 *countp = count;
3223 return vxids;
3224 }
3225
3226 /*
3227 * Examine each existing holder (or awaiter) of the lock.
3228 */
3230 {
3231 proclock = dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
3232
3233 if (conflictMask & proclock->holdMask)
3234 {
3235 PGPROC *proc = proclock->tag.myProc;
3236
3237 /* A backend never blocks itself */
3238 if (proc != MyProc)
3239 {
3241
3242 GET_VXID_FROM_PGPROC(vxid, *proc);
3243
3245 {
3246 int i;
3247
3248 /* Avoid duplicate entries. */
3249 for (i = 0; i < fast_count; ++i)
3251 break;
3252 if (i >= fast_count)
3253 vxids[count++] = vxid;
3254 }
3255 /* else, xact already committed or aborted */
3256 }
3257 }
3258 }
3259
3261
3262 if (count > MaxBackends + max_prepared_xacts) /* should never happen */
3263 elog(PANIC, "too many conflicting locks found");
3264
3265 vxids[count].procNumber = INVALID_PROC_NUMBER;
3266 vxids[count].localTransactionId = InvalidLocalTransactionId;
3267 if (countp)
3268 *countp = count;
3269 return vxids;
3270}
#define lengthof(array)
Definition c.h:875
void * hash_search_with_hash_value(HTAB *hashp, const void *keyPtr, uint32 hashvalue, HASHACTION action, bool *foundPtr)
Definition dynahash.c:965
#define PANIC
Definition elog.h:42
#define palloc0_array(type, count)
Definition fe_memutils.h:77
@ HASH_FIND
Definition hsearch.h:113
#define FAST_PATH_LOCKNUMBER_OFFSET
Definition lock.c:242
#define FAST_PATH_REL_GROUP(rel)
Definition lock.c:217
#define FAST_PATH_SLOT(group, index)
Definition lock.c:224
#define ConflictsWithRelationFastPath(locktag, mode)
Definition lock.c:273
static HTAB * LockMethodLockHash
Definition lock.c:321
#define FAST_PATH_GET_BITS(proc, n)
Definition lock.c:245
uint32 LockTagHashCode(const LOCKTAG *locktag)
Definition lock.c:557
#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:501
#define FP_LOCK_SLOTS_PER_GROUP
Definition proc.h:93
PGPROC * MyProc
Definition proc.c:68
PROC_HDR * ProcGlobal
Definition proc.c:71
uint32 locktag_field1
Definition locktag.h:66
uint32 locktag_field2
Definition locktag.h:67
LWLock fpInfoLock
Definition proc.h:321
Oid * fpRelId
Definition proc.h:323
Oid databaseId
Definition proc.h:198
uint64 * fpLockBits
Definition proc.h:322
uint32 allProcCount
Definition proc.h:456
int max_prepared_xacts
Definition twophase.c:117
#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 527 of file lock.c.

528{
530
533}
#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 3793 of file lock.c.

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

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

1890{
1892}
static ResourceOwner awaitedOwner
Definition lock.c:329
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
Definition lock.c:1792

References awaitedLock, awaitedOwner, and GrantLockLocal().

Referenced by LockErrorCleanup().

◆ GrantLock()

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

Definition at line 1658 of file lock.c.

1659{
1660 lock->nGranted++;
1661 lock->granted[lockmode]++;
1662 lock->grantMask |= LOCKBIT_ON(lockmode);
1663 if (lock->granted[lockmode] == lock->requested[lockmode])
1664 lock->waitMask &= LOCKBIT_OFF(lockmode);
1665 proclock->holdMask |= LOCKBIT_ON(lockmode);
1666 LOCK_PRINT("GrantLock", lock, lockmode);
1667 Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1668 Assert(lock->nGranted <= lock->nRequested);
1669}
#define LOCK_PRINT(where, lock, type)
Definition lock.c:405
#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:1010
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 505 of file lock.c.

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

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

4597{
4598 lock_twophase_postcommit(fxid, info, recdata, len);
4599}
void lock_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4569

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

4571{
4573 PGPROC *proc = TwoPhaseGetDummyProc(fxid, true);
4574 LOCKTAG *locktag;
4577
4578 Assert(len == sizeof(TwoPhaseLockRecord));
4579 locktag = &rec->locktag;
4581
4583 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4585
4586 LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4587}
static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc, LOCKTAG *locktag, LOCKMODE lockmode, bool decrement_strong_lock_count)
Definition lock.c:3284
PGPROC * TwoPhaseGetDummyProc(FullTransactionId fxid, bool lock_held)
Definition twophase.c:926

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

4358{
4360 PGPROC *proc = TwoPhaseGetDummyProc(fxid, false);
4361 LOCKTAG *locktag;
4362 LOCKMODE lockmode;
4364 LOCK *lock;
4365 PROCLOCK *proclock;
4367 bool found;
4368 uint32 hashcode;
4370 int partition;
4373
4374 Assert(len == sizeof(TwoPhaseLockRecord));
4375 locktag = &rec->locktag;
4376 lockmode = rec->lockmode;
4378
4380 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4382
4383 hashcode = LockTagHashCode(locktag);
4384 partition = LockHashPartition(hashcode);
4386
4388
4389 /*
4390 * Find or create a lock with this tag.
4391 */
4393 locktag,
4394 hashcode,
4396 &found);
4397 if (!lock)
4398 {
4400 ereport(ERROR,
4402 errmsg("out of shared memory"),
4403 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4404 }
4405
4406 /*
4407 * if it's a new lock object, initialize it
4408 */
4409 if (!found)
4410 {
4411 lock->grantMask = 0;
4412 lock->waitMask = 0;
4413 dlist_init(&lock->procLocks);
4414 dclist_init(&lock->waitProcs);
4415 lock->nRequested = 0;
4416 lock->nGranted = 0;
4417 MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
4418 MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4419 LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4420 }
4421 else
4422 {
4423 LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
4424 Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
4425 Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4426 Assert(lock->nGranted <= lock->nRequested);
4427 }
4428
4429 /*
4430 * Create the hash key for the proclock table.
4431 */
4432 proclocktag.myLock = lock;
4433 proclocktag.myProc = proc;
4434
4436
4437 /*
4438 * Find or create a proclock entry with this tag
4439 */
4441 &proclocktag,
4444 &found);
4445 if (!proclock)
4446 {
4447 /* Oops, not enough shmem for the proclock */
4448 if (lock->nRequested == 0)
4449 {
4450 /*
4451 * There are no other requestors of this lock, so garbage-collect
4452 * the lock object. We *must* do this to avoid a permanent leak
4453 * of shared memory, because there won't be anything to cause
4454 * anyone to release the lock object later.
4455 */
4458 &(lock->tag),
4459 hashcode,
4461 NULL))
4462 elog(PANIC, "lock table corrupted");
4463 }
4465 ereport(ERROR,
4467 errmsg("out of shared memory"),
4468 errhint("You might need to increase \"%s\".", "max_locks_per_transaction")));
4469 }
4470
4471 /*
4472 * If new, initialize the new entry
4473 */
4474 if (!found)
4475 {
4476 Assert(proc->lockGroupLeader == NULL);
4477 proclock->groupLeader = proc;
4478 proclock->holdMask = 0;
4479 proclock->releaseMask = 0;
4480 /* Add proclock to appropriate lists */
4481 dlist_push_tail(&lock->procLocks, &proclock->lockLink);
4483 &proclock->procLink);
4484 PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
4485 }
4486 else
4487 {
4488 PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
4489 Assert((proclock->holdMask & ~lock->grantMask) == 0);
4490 }
4491
4492 /*
4493 * lock->nRequested and lock->requested[] count the total number of
4494 * requests, whether granted or waiting, so increment those immediately.
4495 */
4496 lock->nRequested++;
4497 lock->requested[lockmode]++;
4498 Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4499
4500 /*
4501 * We shouldn't already hold the desired lock.
4502 */
4503 if (proclock->holdMask & LOCKBIT_ON(lockmode))
4504 elog(ERROR, "lock %s on object %u/%u/%u is already held",
4505 lockMethodTable->lockModeNames[lockmode],
4506 lock->tag.locktag_field1, lock->tag.locktag_field2,
4507 lock->tag.locktag_field3);
4508
4509 /*
4510 * We ignore any possible conflicts and just grant ourselves the lock. Not
4511 * only because we don't bother, but also to avoid deadlocks when
4512 * switching from standby to normal mode. See function comment.
4513 */
4514 GrantLock(lock, proclock, lockmode);
4515
4516 /*
4517 * Bump strong lock count, to make sure any fast-path lock requests won't
4518 * be granted without consulting the primary lock table.
4519 */
4520 if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4521 {
4523
4527 }
4528
4530}
#define MemSet(start, val, len)
Definition c.h:1109
@ HASH_REMOVE
Definition hsearch.h:115
@ HASH_ENTER_NULL
Definition hsearch.h:116
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:605
void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
Definition lock.c:1658
#define PROCLOCK_PRINT(where, proclockP)
Definition lock.c:406
#define LockHashPartition(hashcode)
Definition lock.h:355
@ LW_EXCLUSIVE
Definition lwlock.h:112
uint32 locktag_field3
Definition locktag.h:68
dlist_head myProcLocks[NUM_LOCK_PARTITIONS]
Definition proc.h:318

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

4539{
4541 LOCKTAG *locktag;
4542 LOCKMODE lockmode;
4544
4545 Assert(len == sizeof(TwoPhaseLockRecord));
4546 locktag = &rec->locktag;
4547 lockmode = rec->lockmode;
4549
4551 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4552
4553 if (lockmode == AccessExclusiveLock &&
4554 locktag->locktag_type == LOCKTAG_RELATION)
4555 {
4557 locktag->locktag_field1 /* dboid */ ,
4558 locktag->locktag_field2 /* reloid */ );
4559 }
4560}
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition standby.c:987
#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 836 of file lock.c.

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

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

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

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

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

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

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

◆ LockManagerShmemInit()

void LockManagerShmemInit ( void  )
extern

Definition at line 444 of file lock.c.

445{
446 HASHCTL info;
449 bool found;
450
451 /*
452 * Compute init/max size to request for lock hashtables. Note these
453 * calculations must agree with LockManagerShmemSize!
454 */
457
458 /*
459 * Allocate hash table for LOCK structs. This stores per-locked-object
460 * information.
461 */
462 info.keysize = sizeof(LOCKTAG);
463 info.entrysize = sizeof(LOCK);
465
466 LockMethodLockHash = ShmemInitHash("LOCK hash",
469 &info,
471
472 /* Assume an average of 2 holders per lock */
473 max_table_size *= 2;
474 init_table_size *= 2;
475
476 /*
477 * Allocate hash table for PROCLOCK structs. This stores
478 * per-lock-per-holder information.
479 */
480 info.keysize = sizeof(PROCLOCKTAG);
481 info.entrysize = sizeof(PROCLOCK);
482 info.hash = proclock_hash;
484
485 LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
488 &info,
490
491 /*
492 * Allocate fast-path structures.
493 */
495 ShmemInitStruct("Fast Path Strong Relation Lock Data",
496 sizeof(FastPathStrongRelationLockData), &found);
497 if (!found)
499}
#define HASH_FUNCTION
Definition hsearch.h:98
#define HASH_PARTITION
Definition hsearch.h:92
#define NLOCKENTS()
Definition lock.c:56
static uint32 proclock_hash(const void *key, Size keysize)
Definition lock.c:574
HTAB * ShmemInitHash(const char *name, int64 init_size, int64 max_size, HASHCTL *infoP, int hash_flags)
Definition shmem.c:326
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:381
static void SpinLockInit(volatile slock_t *lock)
Definition spin.h:50
HashValueFunc hash
Definition hsearch.h:78
int64 num_partitions
Definition hsearch.h:68

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

Referenced by CreateOrAttachShmemStructs().

◆ LockManagerShmemSize()

Size LockManagerShmemSize ( void  )
extern

Definition at line 3756 of file lock.c.

3757{
3758 Size size = 0;
3759 long max_table_size;
3760
3761 /* lock hash table */
3763 size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3764
3765 /* proclock hash table */
3766 max_table_size *= 2;
3767 size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3768
3769 /*
3770 * Since NLOCKENTS is only an estimate, add 10% safety margin.
3771 */
3772 size = add_size(size, size / 10);
3773
3774 return size;
3775}
Size hash_estimate_size(int64 num_entries, Size entrysize)
Definition dynahash.c:783
Size add_size(Size s1, Size s2)
Definition shmem.c:485

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

Referenced by CalculateShmemSize().

◆ LockReassignCurrentOwner()

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

Definition at line 2706 of file lock.c.

2707{
2709
2710 Assert(parent != NULL);
2711
2712 if (locallocks == NULL)
2713 {
2714 HASH_SEQ_STATUS status;
2716
2718
2719 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2721 }
2722 else
2723 {
2724 int i;
2725
2726 for (i = nlocks - 1; i >= 0; i--)
2727 LockReassignOwner(locallocks[i], parent);
2728 }
2729}
static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
Definition lock.c:2736
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 2102 of file lock.c.

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

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

2612{
2613 if (locallocks == NULL)
2614 {
2615 HASH_SEQ_STATUS status;
2617
2619
2620 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2622 }
2623 else
2624 {
2625 int i;
2626
2627 for (i = nlocks - 1; i >= 0; i--)
2629 }
2630}
static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
Definition lock.c:2646

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

Referenced by ResourceOwnerReleaseInternal().

◆ LockReleaseSession()

void LockReleaseSession ( LOCKMETHODID  lockmethodid)
extern

Definition at line 2581 of file lock.c.

2582{
2583 HASH_SEQ_STATUS status;
2585
2587 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2588
2590
2591 while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2592 {
2593 /* Ignore items that are not of the specified lock method */
2595 continue;
2596
2598 }
2599}

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

558{
559 return get_hash_value(LockMethodLockHash, locktag);
560}
uint32 get_hash_value(HTAB *hashp, const void *keyPtr)
Definition dynahash.c:908

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

4854{
4856 LOCK *lock;
4857 bool found;
4858 uint32 hashcode;
4860 int waiters = 0;
4861
4863 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4864
4865 hashcode = LockTagHashCode(locktag);
4868
4870 locktag,
4871 hashcode,
4872 HASH_FIND,
4873 &found);
4874 if (found)
4875 {
4876 Assert(lock != NULL);
4877 waiters = lock->nRequested;
4878 }
4880
4881 return waiters;
4882}

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

1921{
1922 Assert(locallock->nLocks > 0);
1923 locallock->lockCleared = true;
1924}

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

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

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

2047{
2048 LOCK *waitLock = proc->waitLock;
2049 PROCLOCK *proclock = proc->waitProcLock;
2050 LOCKMODE lockmode = proc->waitLockMode;
2052
2053 /* Make sure proc is waiting */
2056 Assert(waitLock);
2057 Assert(!dclist_is_empty(&waitLock->waitProcs));
2059
2060 /* Remove proc from lock's wait queue */
2062
2063 /* Undo increments of request counts by waiting process */
2064 Assert(waitLock->nRequested > 0);
2065 Assert(waitLock->nRequested > proc->waitLock->nGranted);
2066 waitLock->nRequested--;
2067 Assert(waitLock->requested[lockmode] > 0);
2068 waitLock->requested[lockmode]--;
2069 /* don't forget to clear waitMask bit if appropriate */
2070 if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
2071 waitLock->waitMask &= LOCKBIT_OFF(lockmode);
2072
2073 /* Clean up the proc's own state, and pass it the ok/fail signal */
2074 proc->waitLock = NULL;
2075 proc->waitProcLock = NULL;
2077
2078 /*
2079 * Delete the proclock immediately if it represents no already-held locks.
2080 * (This must happen now because if the owner of the lock decides to
2081 * release it, and the requested/granted counts then go to zero,
2082 * LockRelease expects there to be no remaining proclocks.) Then see if
2083 * any other waiters for the lock can be woken up now.
2084 */
2085 CleanUpLock(waitLock, proclock,
2086 LockMethods[lockmethodid], hashcode,
2087 true);
2088}
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:303
dlist_node waitLink
Definition proc.h:302
ProcWaitStatus waitStatus
Definition proc.h:311

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

1908{
1909 awaitedLock = NULL;
1910}

References awaitedLock, and fb().

Referenced by LockErrorCleanup().

◆ VirtualXactLock()

bool VirtualXactLock ( VirtualTransactionId  vxid,
bool  wait 
)
extern

Definition at line 4742 of file lock.c.

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

4643{
4644 bool fastpath;
4645 LocalTransactionId lxid;
4646
4648
4649 /*
4650 * Clean up shared memory state.
4651 */
4653
4654 fastpath = MyProc->fpVXIDLock;
4656 MyProc->fpVXIDLock = false;
4658
4660
4661 /*
4662 * If fpVXIDLock has been cleared without touching fpLocalTransactionId,
4663 * that means someone transferred the lock to the main lock table.
4664 */
4665 if (!fastpath && LocalTransactionIdIsValid(lxid))
4666 {
4668 LOCKTAG locktag;
4669
4670 vxid.procNumber = MyProcNumber;
4671 vxid.localTransactionId = lxid;
4672 SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid);
4673
4675 &locktag, ExclusiveLock, false);
4676 }
4677}
uint32 LocalTransactionId
Definition c.h:740
ProcNumber MyProcNumber
Definition globals.c:90
#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 54 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