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/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  LOCKTAG
 
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 DEFAULT_LOCKMETHOD   1
 
#define USER_LOCKMETHOD   2
 
#define LOCKTAG_LAST_TYPE   LOCKTAG_APPLY_TRANSACTION
 
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
 
#define SET_LOCKTAG_RELATION_EXTEND(locktag, dboid, reloid)
 
#define SET_LOCKTAG_DATABASE_FROZEN_IDS(locktag, dboid)
 
#define SET_LOCKTAG_PAGE(locktag, dboid, reloid, blocknum)
 
#define SET_LOCKTAG_TUPLE(locktag, dboid, reloid, blocknum, offnum)
 
#define SET_LOCKTAG_TRANSACTION(locktag, xid)
 
#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
 
#define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag, xid, token)
 
#define SET_LOCKTAG_OBJECT(locktag, dboid, classoid, objoid, objsubid)
 
#define SET_LOCKTAG_ADVISORY(locktag, id1, id2, id3, id4)
 
#define SET_LOCKTAG_APPLY_TRANSACTION(locktag, dboid, suboid, xid, objid)
 
#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 uint16 LOCKMETHODID
 
typedef enum LockTagType LockTagType
 
typedef struct LOCKTAG LOCKTAG
 
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  LockTagType {
  LOCKTAG_RELATION , LOCKTAG_RELATION_EXTEND , LOCKTAG_DATABASE_FROZEN_IDS , LOCKTAG_PAGE ,
  LOCKTAG_TUPLE , LOCKTAG_TRANSACTION , LOCKTAG_VIRTUALTRANSACTION , LOCKTAG_SPECULATIVE_TOKEN ,
  LOCKTAG_OBJECT , LOCKTAG_USERLOCK , LOCKTAG_ADVISORY , LOCKTAG_APPLY_TRANSACTION
}
 
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
 
PGDLLIMPORT const char *const LockTagTypeNames []
 

Macro Definition Documentation

◆ DEFAULT_LOCKMETHOD

#define DEFAULT_LOCKMETHOD   1

Definition at line 127 of file lock.h.

◆ 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 79 of file lock.h.

110{
111 int numLockModes;
112 const LOCKMASK *conflictTab;
113 const char *const *lockModeNames;
114 const bool *trace_flag;
116
117typedef const LockMethodData *LockMethod;
118
119/*
120 * Lock methods are identified by LOCKMETHODID. (Despite the declaration as
121 * uint16, we are constrained to 256 lockmethods by the layout of LOCKTAG.)
122 */
123typedef uint16 LOCKMETHODID;
124
125/* These identify the known lock methods */
126#define DEFAULT_LOCKMETHOD 1
127#define USER_LOCKMETHOD 2
128
129/*
130 * LOCKTAG is the key information needed to look up a LOCK item in the
131 * lock hashtable. A LOCKTAG value uniquely identifies a lockable object.
132 *
133 * The LockTagType enum defines the different kinds of objects we can lock.
134 * We can handle up to 256 different LockTagTypes.
135 */
136typedef enum LockTagType
137{
138 LOCKTAG_RELATION, /* whole relation */
139 LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */
140 LOCKTAG_DATABASE_FROZEN_IDS, /* pg_database.datfrozenxid */
141 LOCKTAG_PAGE, /* one page of a relation */
142 LOCKTAG_TUPLE, /* one physical tuple */
143 LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */
144 LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */
145 LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */
146 LOCKTAG_OBJECT, /* non-relation database object */
147 LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */
148 LOCKTAG_ADVISORY, /* advisory user locks */
149 LOCKTAG_APPLY_TRANSACTION, /* transaction being applied on a logical
150 * replication subscriber */
152
153#define LOCKTAG_LAST_TYPE LOCKTAG_APPLY_TRANSACTION
154
155extern PGDLLIMPORT const char *const LockTagTypeNames[];
156
157/*
158 * The LOCKTAG struct is defined with malice aforethought to fit into 16
159 * bytes with no padding. Note that this would need adjustment if we were
160 * to widen Oid, BlockNumber, or TransactionId to more than 32 bits.
161 *
162 * We include lockmethodid in the locktag so that a single hash table in
163 * shared memory can store locks of different lockmethods.
164 */
165typedef struct LOCKTAG
166{
167 uint32 locktag_field1; /* a 32-bit ID field */
168 uint32 locktag_field2; /* a 32-bit ID field */
169 uint32 locktag_field3; /* a 32-bit ID field */
170 uint16 locktag_field4; /* a 16-bit ID field */
171 uint8 locktag_type; /* see enum LockTagType */
172 uint8 locktag_lockmethodid; /* lockmethod indicator */
173} LOCKTAG;
174
175/*
176 * These macros define how we map logical IDs of lockable objects into
177 * the physical fields of LOCKTAG. Use these to set up LOCKTAG values,
178 * rather than accessing the fields directly. Note multiple eval of target!
179 */
180
181/* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */
182#define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \
183 ((locktag).locktag_field1 = (dboid), \
184 (locktag).locktag_field2 = (reloid), \
185 (locktag).locktag_field3 = 0, \
186 (locktag).locktag_field4 = 0, \
187 (locktag).locktag_type = LOCKTAG_RELATION, \
188 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
189
190/* same ID info as RELATION */
191#define SET_LOCKTAG_RELATION_EXTEND(locktag,dboid,reloid) \
192 ((locktag).locktag_field1 = (dboid), \
193 (locktag).locktag_field2 = (reloid), \
194 (locktag).locktag_field3 = 0, \
195 (locktag).locktag_field4 = 0, \
196 (locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \
197 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
198
199/* ID info for frozen IDs is DB OID */
200#define SET_LOCKTAG_DATABASE_FROZEN_IDS(locktag,dboid) \
201 ((locktag).locktag_field1 = (dboid), \
202 (locktag).locktag_field2 = 0, \
203 (locktag).locktag_field3 = 0, \
204 (locktag).locktag_field4 = 0, \
205 (locktag).locktag_type = LOCKTAG_DATABASE_FROZEN_IDS, \
206 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
207
208/* ID info for a page is RELATION info + BlockNumber */
209#define SET_LOCKTAG_PAGE(locktag,dboid,reloid,blocknum) \
210 ((locktag).locktag_field1 = (dboid), \
211 (locktag).locktag_field2 = (reloid), \
212 (locktag).locktag_field3 = (blocknum), \
213 (locktag).locktag_field4 = 0, \
214 (locktag).locktag_type = LOCKTAG_PAGE, \
215 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
216
217/* ID info for a tuple is PAGE info + OffsetNumber */
218#define SET_LOCKTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \
219 ((locktag).locktag_field1 = (dboid), \
220 (locktag).locktag_field2 = (reloid), \
221 (locktag).locktag_field3 = (blocknum), \
222 (locktag).locktag_field4 = (offnum), \
223 (locktag).locktag_type = LOCKTAG_TUPLE, \
224 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
225
226/* ID info for a transaction is its TransactionId */
227#define SET_LOCKTAG_TRANSACTION(locktag,xid) \
228 ((locktag).locktag_field1 = (xid), \
229 (locktag).locktag_field2 = 0, \
230 (locktag).locktag_field3 = 0, \
231 (locktag).locktag_field4 = 0, \
232 (locktag).locktag_type = LOCKTAG_TRANSACTION, \
233 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
234
235/* ID info for a virtual transaction is its VirtualTransactionId */
236#define SET_LOCKTAG_VIRTUALTRANSACTION(locktag,vxid) \
237 ((locktag).locktag_field1 = (vxid).procNumber, \
238 (locktag).locktag_field2 = (vxid).localTransactionId, \
239 (locktag).locktag_field3 = 0, \
240 (locktag).locktag_field4 = 0, \
241 (locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \
242 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
243
244/*
245 * ID info for a speculative insert is TRANSACTION info +
246 * its speculative insert counter.
247 */
248#define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag,xid,token) \
249 ((locktag).locktag_field1 = (xid), \
250 (locktag).locktag_field2 = (token), \
251 (locktag).locktag_field3 = 0, \
252 (locktag).locktag_field4 = 0, \
253 (locktag).locktag_type = LOCKTAG_SPECULATIVE_TOKEN, \
254 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
255
256/*
257 * ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID
258 *
259 * Note: object ID has same representation as in pg_depend and
260 * pg_description, but notice that we are constraining SUBID to 16 bits.
261 * Also, we use DB OID = 0 for shared objects such as tablespaces.
262 */
263#define SET_LOCKTAG_OBJECT(locktag,dboid,classoid,objoid,objsubid) \
264 ((locktag).locktag_field1 = (dboid), \
265 (locktag).locktag_field2 = (classoid), \
266 (locktag).locktag_field3 = (objoid), \
267 (locktag).locktag_field4 = (objsubid), \
268 (locktag).locktag_type = LOCKTAG_OBJECT, \
269 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
270
271#define SET_LOCKTAG_ADVISORY(locktag,id1,id2,id3,id4) \
272 ((locktag).locktag_field1 = (id1), \
273 (locktag).locktag_field2 = (id2), \
274 (locktag).locktag_field3 = (id3), \
275 (locktag).locktag_field4 = (id4), \
276 (locktag).locktag_type = LOCKTAG_ADVISORY, \
277 (locktag).locktag_lockmethodid = USER_LOCKMETHOD)
278
279/*
280 * ID info for a remote transaction on a logical replication subscriber is: DB
281 * OID + SUBSCRIPTION OID + TRANSACTION ID + OBJID
282 */
283#define SET_LOCKTAG_APPLY_TRANSACTION(locktag,dboid,suboid,xid,objid) \
284 ((locktag).locktag_field1 = (dboid), \
285 (locktag).locktag_field2 = (suboid), \
286 (locktag).locktag_field3 = (xid), \
287 (locktag).locktag_field4 = (objid), \
288 (locktag).locktag_type = LOCKTAG_APPLY_TRANSACTION, \
289 (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
290
291/*
292 * Per-locked-object lock information:
293 *
294 * tag -- uniquely identifies the object being locked
295 * grantMask -- bitmask for all lock types currently granted on this object.
296 * waitMask -- bitmask for all lock types currently awaited on this object.
297 * procLocks -- list of PROCLOCK objects for this lock.
298 * waitProcs -- queue of processes waiting for this lock.
299 * requested -- count of each lock type currently requested on the lock
300 * (includes requests already granted!!).
301 * nRequested -- total requested locks of all types.
302 * granted -- count of each lock type currently granted on the lock.
303 * nGranted -- total granted locks of all types.
304 *
305 * Note: these counts count 1 for each backend. Internally to a backend,
306 * there may be multiple grabs on a particular lock, but this is not reflected
307 * into shared memory.
308 */
309typedef struct LOCK
310{
311 /* hash key */
312 LOCKTAG tag; /* unique identifier of lockable object */
313
314 /* data */
315 LOCKMASK grantMask; /* bitmask for lock types already granted */
316 LOCKMASK waitMask; /* bitmask for lock types awaited */
317 dlist_head procLocks; /* list of PROCLOCK objects assoc. with lock */
318 dclist_head waitProcs; /* list of PGPROC objects waiting on lock */
319 int requested[MAX_LOCKMODES]; /* counts of requested locks */
320 int nRequested; /* total of requested[] array */
321 int granted[MAX_LOCKMODES]; /* counts of granted locks */
322 int nGranted; /* total of granted[] array */
323} LOCK;
324
325#define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
326#define LOCK_LOCKTAG(lock) ((LockTagType) (lock).tag.locktag_type)
327
328
329/*
330 * We may have several different backends holding or awaiting locks
331 * on the same lockable object. We need to store some per-holder/waiter
332 * information for each such holder (or would-be holder). This is kept in
333 * a PROCLOCK struct.
334 *
335 * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the
336 * proclock hashtable. A PROCLOCKTAG value uniquely identifies the combination
337 * of a lockable object and a holder/waiter for that object. (We can use
338 * pointers here because the PROCLOCKTAG need only be unique for the lifespan
339 * of the PROCLOCK, and it will never outlive the lock or the proc.)
340 *
341 * Internally to a backend, it is possible for the same lock to be held
342 * for different purposes: the backend tracks transaction locks separately
343 * from session locks. However, this is not reflected in the shared-memory
344 * state: we only track which backend(s) hold the lock. This is OK since a
345 * backend can never block itself.
346 *
347 * The holdMask field shows the already-granted locks represented by this
348 * proclock. Note that there will be a proclock object, possibly with
349 * zero holdMask, for any lock that the process is currently waiting on.
350 * Otherwise, proclock objects whose holdMasks are zero are recycled
351 * as soon as convenient.
352 *
353 * releaseMask is workspace for LockReleaseAll(): it shows the locks due
354 * to be released during the current call. This must only be examined or
355 * set by the backend owning the PROCLOCK.
356 *
357 * Each PROCLOCK object is linked into lists for both the associated LOCK
358 * object and the owning PGPROC object. Note that the PROCLOCK is entered
359 * into these lists as soon as it is created, even if no lock has yet been
360 * granted. A PGPROC that is waiting for a lock to be granted will also be
361 * linked into the lock's waitProcs queue.
362 */
363typedef struct PROCLOCKTAG
364{
365 /* NB: we assume this struct contains no padding! */
366 LOCK *myLock; /* link to per-lockable-object information */
367 PGPROC *myProc; /* link to PGPROC of owning backend */
369
370typedef struct PROCLOCK
371{
372 /* tag */
373 PROCLOCKTAG tag; /* unique identifier of proclock object */
374
375 /* data */
376 PGPROC *groupLeader; /* proc's lock group leader, or proc itself */
377 LOCKMASK holdMask; /* bitmask for lock types currently held */
378 LOCKMASK releaseMask; /* bitmask for lock types to be released */
379 dlist_node lockLink; /* list link in LOCK's list of proclocks */
380 dlist_node procLink; /* list link in PGPROC's list of proclocks */
381} PROCLOCK;
382
383#define PROCLOCK_LOCKMETHOD(proclock) \
384 LOCK_LOCKMETHOD(*((proclock).tag.myLock))
385
386/*
387 * Each backend also maintains a local hash table with information about each
388 * lock it is currently interested in. In particular the local table counts
389 * the number of times that lock has been acquired. This allows multiple
390 * requests for the same lock to be executed without additional accesses to
391 * shared memory. We also track the number of lock acquisitions per
392 * ResourceOwner, so that we can release just those locks belonging to a
393 * particular ResourceOwner.
394 *
395 * When holding a lock taken "normally", the lock and proclock fields always
396 * point to the associated objects in shared memory. However, if we acquired
397 * the lock via the fast-path mechanism, the lock and proclock fields are set
398 * to NULL, since there probably aren't any such objects in shared memory.
399 * (If the lock later gets promoted to normal representation, we may eventually
400 * update our locallock's lock/proclock fields after finding the shared
401 * objects.)
402 *
403 * Caution: a locallock object can be left over from a failed lock acquisition
404 * attempt. In this case its lock/proclock fields are untrustworthy, since
405 * the shared lock object is neither held nor awaited, and hence is available
406 * to be reclaimed. If nLocks > 0 then these pointers must either be valid or
407 * NULL, but when nLocks == 0 they should be considered garbage.
408 */
409typedef struct LOCALLOCKTAG
410{
411 LOCKTAG lock; /* identifies the lockable object */
412 LOCKMODE mode; /* lock mode for this table entry */
414
415typedef struct LOCALLOCKOWNER
416{
417 /*
418 * Note: if owner is NULL then the lock is held on behalf of the session;
419 * otherwise it is held on behalf of my current transaction.
420 *
421 * Must use a forward struct reference to avoid circularity.
422 */
423 struct ResourceOwnerData *owner;
424 int64 nLocks; /* # of times held by this owner */
426
427typedef struct LOCALLOCK
428{
429 /* tag */
430 LOCALLOCKTAG tag; /* unique identifier of locallock entry */
431
432 /* data */
433 uint32 hashcode; /* copy of LOCKTAG's hash value */
434 LOCK *lock; /* associated LOCK object, if any */
435 PROCLOCK *proclock; /* associated PROCLOCK object, if any */
436 int64 nLocks; /* total number of times lock is held */
437 int numLockOwners; /* # of relevant ResourceOwners */
438 int maxLockOwners; /* allocated size of array */
439 LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */
440 bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */
441 bool lockCleared; /* we read all sinval msgs for lock */
442} LOCALLOCK;
443
444#define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid)
445#define LOCALLOCK_LOCKTAG(llock) ((LockTagType) (llock).tag.lock.locktag_type)
446
447
448/*
449 * These structures hold information passed from lmgr internals to the lock
450 * listing user-level functions (in lockfuncs.c).
451 */
452
453typedef struct LockInstanceData
454{
455 LOCKTAG locktag; /* tag for locked object */
456 LOCKMASK holdMask; /* locks held by this PGPROC */
457 LOCKMODE waitLockMode; /* lock awaited by this PGPROC, if any */
458 VirtualTransactionId vxid; /* virtual transaction ID of this PGPROC */
459 TimestampTz waitStart; /* time at which this PGPROC started waiting
460 * for lock */
461 int pid; /* pid of this PGPROC */
462 int leaderPid; /* pid of group leader; = pid if no group */
463 bool fastpath; /* taken via fastpath? */
465
466typedef struct LockData
467{
468 int nelements; /* The length of the array */
469 LockInstanceData *locks; /* Array of per-PROCLOCK information */
470} LockData;
471
472typedef struct BlockedProcData
473{
474 int pid; /* pid of a blocked PGPROC */
475 /* Per-PROCLOCK information about PROCLOCKs of the lock the pid awaits */
476 /* (these fields refer to indexes in BlockedProcsData.locks[]) */
477 int first_lock; /* index of first relevant LockInstanceData */
478 int num_locks; /* number of relevant LockInstanceDatas */
479 /* PIDs of PGPROCs that are ahead of "pid" in the lock's wait queue */
480 /* (these fields refer to indexes in BlockedProcsData.waiter_pids[]) */
481 int first_waiter; /* index of first preceding waiter */
482 int num_waiters; /* number of preceding waiters */
484
485typedef struct BlockedProcsData
486{
487 BlockedProcData *procs; /* Array of per-blocked-proc information */
488 LockInstanceData *locks; /* Array of per-PROCLOCK information */
489 int *waiter_pids; /* Array of PIDs of other blocked PGPROCs */
490 int nprocs; /* # of valid entries in procs[] array */
491 int maxprocs; /* Allocated length of procs[] array */
492 int nlocks; /* # of valid entries in locks[] array */
493 int maxlocks; /* Allocated length of locks[] array */
494 int npids; /* # of valid entries in waiter_pids[] array */
495 int maxpids; /* Allocated length of waiter_pids[] array */
497
498
499/* Result codes for LockAcquire() */
500typedef enum
501{
502 LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
503 LOCKACQUIRE_OK, /* lock successfully acquired */
504 LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
505 LOCKACQUIRE_ALREADY_CLEAR, /* incremented count for lock already clear */
507
508/* Deadlock states identified by DeadLockCheck() */
509typedef enum
510{
511 DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
512 DS_NO_DEADLOCK, /* no deadlock detected */
513 DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
514 DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
515 DS_BLOCKED_BY_AUTOVACUUM, /* no deadlock; queue blocked by autovacuum
516 * worker */
518
519/*
520 * The lockmgr's shared hash tables are partitioned to reduce contention.
521 * To determine which partition a given locktag belongs to, compute the tag's
522 * hash code with LockTagHashCode(), then apply one of these macros.
523 * NB: NUM_LOCK_PARTITIONS must be a power of 2!
524 */
525#define LockHashPartition(hashcode) \
526 ((hashcode) % NUM_LOCK_PARTITIONS)
527#define LockHashPartitionLock(hashcode) \
528 (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + \
529 LockHashPartition(hashcode)].lock)
530#define LockHashPartitionLockByIndex(i) \
531 (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock)
532
533/*
534 * The deadlock detector needs to be able to access lockGroupLeader and
535 * related fields in the PGPROC, so we arrange for those fields to be protected
536 * by one of the lock hash partition locks. Since the deadlock detector
537 * acquires all such locks anyway, this makes it safe for it to access these
538 * fields without doing anything extra. To avoid contention as much as
539 * possible, we map different PGPROCs to different partition locks. The lock
540 * used for a given lock group is determined by the group leader's pgprocno.
541 */
542#define LockHashPartitionLockByProc(leader_pgproc) \
543 LockHashPartitionLock(GetNumberFromPGProc(leader_pgproc))
544
545/*
546 * function prototypes
547 */
548extern void LockManagerShmemInit(void);
549extern Size LockManagerShmemSize(void);
550extern void InitLockManagerAccess(void);
551extern LockMethod GetLocksMethodTable(const LOCK *lock);
552extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag);
553extern uint32 LockTagHashCode(const LOCKTAG *locktag);
555extern LockAcquireResult LockAcquire(const LOCKTAG *locktag,
556 LOCKMODE lockmode,
557 bool sessionLock,
558 bool dontWait);
559extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag,
560 LOCKMODE lockmode,
561 bool sessionLock,
562 bool dontWait,
565 bool logLockFailure);
566extern void AbortStrongLockAcquire(void);
567extern void MarkLockClear(LOCALLOCK *locallock);
568extern bool LockRelease(const LOCKTAG *locktag,
569 LOCKMODE lockmode, bool sessionLock);
572extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks);
573extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks);
574extern bool LockHeldByMe(const LOCKTAG *locktag,
575 LOCKMODE lockmode, bool orstronger);
576#ifdef USE_ASSERT_CHECKING
577extern HTAB *GetLockMethodLocalHash(void);
578#endif
579extern bool LockHasWaiters(const LOCKTAG *locktag,
580 LOCKMODE lockmode, bool sessionLock);
581extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag,
582 LOCKMODE lockmode, int *countp);
583extern void AtPrepare_Locks(void);
584extern void PostPrepare_Locks(FullTransactionId fxid);
586 LOCKMODE lockmode,
587 LOCK *lock, PROCLOCK *proclock);
588extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode);
589extern void GrantAwaitedLock(void);
590extern LOCALLOCK *GetAwaitedLock(void);
591extern void ResetAwaitedLock(void);
592
593extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode);
594extern LockData *GetLockStatusData(void);
596
599
600extern void lock_twophase_recover(FullTransactionId fxid, uint16 info,
601 void *recdata, uint32 len);
603 void *recdata, uint32 len);
605 void *recdata, uint32 len);
607 void *recdata, uint32 len);
608
611pg_noreturn extern void DeadLockReport(void);
613 LOCKMODE lockmode,
614 LOCK *lock,
615 PGPROC *proc2);
616extern void InitDeadLockChecking(void);
617
618extern int LockWaiterCount(const LOCKTAG *locktag);
619
620#ifdef LOCK_DEBUG
621extern void DumpLocks(PGPROC *proc);
622extern void DumpAllLocks(void);
623#endif
624
625/* Lock a VXID (used to wait for a transaction to finish) */
627extern void VirtualXactLockTableCleanup(void);
628extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait);
629
630#endif /* LOCK_H_ */
#define PGDLLIMPORT
Definition c.h:1328
uint8_t uint8
Definition c.h:544
#define pg_noreturn
Definition c.h:164
int64_t int64
Definition c.h:543
uint16_t uint16
Definition c.h:545
uint32_t uint32
Definition c.h:546
size_t Size
Definition c.h:619
int64 TimestampTz
Definition timestamp.h:39
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition lock.c:809
uint16 LOCKMETHODID
Definition lock.h:124
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:4596
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:4538
bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
Definition lock.c:623
const LockMethodData * LockMethod
Definition lock.h:118
void VirtualXactLockTableInsert(VirtualTransactionId vxid)
Definition lock.c:4620
PGPROC * GetBlockingAutoVacuumPgproc(void)
Definition deadlock.c:290
LockTagType
Definition lock.h:138
@ LOCKTAG_OBJECT
Definition lock.h:147
@ LOCKTAG_RELATION_EXTEND
Definition lock.h:140
@ LOCKTAG_RELATION
Definition lock.h:139
@ LOCKTAG_TUPLE
Definition lock.h:143
@ LOCKTAG_SPECULATIVE_TOKEN
Definition lock.h:146
@ LOCKTAG_APPLY_TRANSACTION
Definition lock.h:150
@ LOCKTAG_USERLOCK
Definition lock.h:148
@ LOCKTAG_DATABASE_FROZEN_IDS
Definition lock.h:141
@ LOCKTAG_VIRTUALTRANSACTION
Definition lock.h:145
@ LOCKTAG_TRANSACTION
Definition lock.h:144
@ LOCKTAG_PAGE
Definition lock.h:142
@ LOCKTAG_ADVISORY
Definition lock.h:149
void GrantAwaitedLock(void)
Definition lock.c:1889
int LockWaiterCount(const LOCKTAG *locktag)
Definition lock.c:4854
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:4643
bool VirtualXactLock(VirtualTransactionId vxid, bool wait)
Definition lock.c:4743
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:511
@ DS_HARD_DEADLOCK
Definition lock.h:515
@ DS_BLOCKED_BY_AUTOVACUUM
Definition lock.h:516
@ DS_NO_DEADLOCK
Definition lock.h:513
@ DS_NOT_YET_CHECKED
Definition lock.h:512
@ DS_SOFT_DEADLOCK
Definition lock.h:514
BlockedProcsData * GetBlockerStatusData(int blocked_pid)
Definition lock.c:3996
#define MAX_LOCKMODES
Definition lock.h:84
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:4253
void lock_twophase_postcommit(FullTransactionId fxid, uint16 info, void *recdata, uint32 len)
Definition lock.c:4570
PGDLLIMPORT const char *const LockTagTypeNames[]
Definition lockfuncs.c:28
void InitDeadLockChecking(void)
Definition deadlock.c:144
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:4357
pg_noreturn void DeadLockReport(void)
Definition deadlock.c:1075
LockMethod GetLocksMethodTable(const LOCK *lock)
Definition lock.c:527
LockAcquireResult
Definition lock.h:502
@ LOCKACQUIRE_ALREADY_CLEAR
Definition lock.h:506
@ LOCKACQUIRE_OK
Definition lock.h:504
@ LOCKACQUIRE_ALREADY_HELD
Definition lock.h:505
@ LOCKACQUIRE_NOT_AVAIL
Definition lock.h:503
xl_standby_lock * GetRunningTransactionLocks(int *nlocks)
Definition lock.c:4171
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
Definition lock.c:539
int LOCKMODE
Definition lockdefs.h:26
int LOCKMASK
Definition lockdefs.h:25
static PgChecksumMode mode
const void size_t len
int first_lock
Definition lock.h:478
int first_waiter
Definition lock.h:482
int num_waiters
Definition lock.h:483
int num_locks
Definition lock.h:479
LockInstanceData * locks
Definition lock.h:489
int * waiter_pids
Definition lock.h:490
BlockedProcData * procs
Definition lock.h:488
int64 nLocks
Definition lock.h:425
struct ResourceOwnerData * owner
Definition lock.h:424
LOCKTAG lock
Definition lock.h:412
LOCKMODE mode
Definition lock.h:413
LOCALLOCKOWNER * lockOwners
Definition lock.h:440
uint32 hashcode
Definition lock.h:434
int maxLockOwners
Definition lock.h:439
LOCK * lock
Definition lock.h:435
int64 nLocks
Definition lock.h:437
int numLockOwners
Definition lock.h:438
bool holdsStrongLockCount
Definition lock.h:441
PROCLOCK * proclock
Definition lock.h:436
LOCALLOCKTAG tag
Definition lock.h:431
bool lockCleared
Definition lock.h:442
uint8 locktag_type
Definition lock.h:172
uint32 locktag_field3
Definition lock.h:170
uint32 locktag_field1
Definition lock.h:168
uint8 locktag_lockmethodid
Definition lock.h:173
uint16 locktag_field4
Definition lock.h:171
uint32 locktag_field2
Definition lock.h:169
Definition lock.h:311
int nRequested
Definition lock.h:321
LOCKTAG tag
Definition lock.h:313
int requested[MAX_LOCKMODES]
Definition lock.h:320
dclist_head waitProcs
Definition lock.h:319
int granted[MAX_LOCKMODES]
Definition lock.h:322
LOCKMASK grantMask
Definition lock.h:316
LOCKMASK waitMask
Definition lock.h:317
int nGranted
Definition lock.h:323
dlist_head procLocks
Definition lock.h:318
LockInstanceData * locks
Definition lock.h:470
int nelements
Definition lock.h:469
LOCKMASK holdMask
Definition lock.h:457
LOCKMODE waitLockMode
Definition lock.h:458
bool fastpath
Definition lock.h:464
LOCKTAG locktag
Definition lock.h:456
TimestampTz waitStart
Definition lock.h:460
VirtualTransactionId vxid
Definition lock.h:459
Definition proc.h:179
LOCK * myLock
Definition lock.h:367
PGPROC * myProc
Definition lock.h:368
LOCKMASK holdMask
Definition lock.h:378
dlist_node lockLink
Definition lock.h:380
PGPROC * groupLeader
Definition lock.h:377
LOCKMASK releaseMask
Definition lock.h:379
PROCLOCKTAG tag
Definition lock.h:374
dlist_node procLink
Definition lock.h:381

◆ InvalidLocalTransactionId

#define InvalidLocalTransactionId   0

Definition at line 67 of file lock.h.

◆ LOCALLOCK_LOCKMETHOD

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

Definition at line 445 of file lock.h.

◆ LOCALLOCK_LOCKTAG

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

Definition at line 446 of file lock.h.

◆ LocalTransactionIdIsValid

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

Definition at line 68 of file lock.h.

◆ LOCK_LOCKMETHOD

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

Definition at line 326 of file lock.h.

◆ LOCK_LOCKTAG

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

Definition at line 327 of file lock.h.

◆ LOCKBIT_OFF

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

Definition at line 87 of file lock.h.

◆ LOCKBIT_ON

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

Definition at line 86 of file lock.h.

◆ LockHashPartition

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

Definition at line 526 of file lock.h.

◆ LockHashPartitionLock

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

Definition at line 528 of file lock.h.

◆ LockHashPartitionLockByIndex

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

Definition at line 531 of file lock.h.

◆ LockHashPartitionLockByProc

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

Definition at line 543 of file lock.h.

◆ LOCKTAG_LAST_TYPE

#define LOCKTAG_LAST_TYPE   LOCKTAG_APPLY_TRANSACTION

Definition at line 154 of file lock.h.

◆ MAX_LOCKMODES

#define MAX_LOCKMODES   10

Definition at line 84 of file lock.h.

◆ PROCLOCK_LOCKMETHOD

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

Definition at line 384 of file lock.h.

◆ SET_LOCKTAG_ADVISORY

#define SET_LOCKTAG_ADVISORY (   locktag,
  id1,
  id2,
  id3,
  id4 
)
Value:
((locktag).locktag_field1 = (id1), \
(locktag).locktag_field2 = (id2), \
(locktag).locktag_field3 = (id3), \
(locktag).locktag_field4 = (id4), \
(locktag).locktag_type = LOCKTAG_ADVISORY, \
(locktag).locktag_lockmethodid = USER_LOCKMETHOD)
#define USER_LOCKMETHOD
Definition lock.h:128

Definition at line 272 of file lock.h.

◆ SET_LOCKTAG_APPLY_TRANSACTION

#define SET_LOCKTAG_APPLY_TRANSACTION (   locktag,
  dboid,
  suboid,
  xid,
  objid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (suboid), \
(locktag).locktag_field3 = (xid), \
(locktag).locktag_field4 = (objid), \
(locktag).locktag_type = LOCKTAG_APPLY_TRANSACTION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)
#define DEFAULT_LOCKMETHOD
Definition lock.h:127

Definition at line 284 of file lock.h.

◆ SET_LOCKTAG_DATABASE_FROZEN_IDS

#define SET_LOCKTAG_DATABASE_FROZEN_IDS (   locktag,
  dboid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = 0, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_DATABASE_FROZEN_IDS, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 201 of file lock.h.

◆ SET_LOCKTAG_OBJECT

#define SET_LOCKTAG_OBJECT (   locktag,
  dboid,
  classoid,
  objoid,
  objsubid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (classoid), \
(locktag).locktag_field3 = (objoid), \
(locktag).locktag_field4 = (objsubid), \
(locktag).locktag_type = LOCKTAG_OBJECT, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 264 of file lock.h.

◆ SET_LOCKTAG_PAGE

#define SET_LOCKTAG_PAGE (   locktag,
  dboid,
  reloid,
  blocknum 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = (blocknum), \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_PAGE, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 210 of file lock.h.

◆ SET_LOCKTAG_RELATION

#define SET_LOCKTAG_RELATION (   locktag,
  dboid,
  reloid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_RELATION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 183 of file lock.h.

◆ SET_LOCKTAG_RELATION_EXTEND

#define SET_LOCKTAG_RELATION_EXTEND (   locktag,
  dboid,
  reloid 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 192 of file lock.h.

◆ SET_LOCKTAG_SPECULATIVE_INSERTION

#define SET_LOCKTAG_SPECULATIVE_INSERTION (   locktag,
  xid,
  token 
)
Value:
((locktag).locktag_field1 = (xid), \
(locktag).locktag_field2 = (token), \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_SPECULATIVE_TOKEN, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 249 of file lock.h.

◆ SET_LOCKTAG_TRANSACTION

#define SET_LOCKTAG_TRANSACTION (   locktag,
  xid 
)
Value:
((locktag).locktag_field1 = (xid), \
(locktag).locktag_field2 = 0, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_TRANSACTION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 228 of file lock.h.

◆ SET_LOCKTAG_TUPLE

#define SET_LOCKTAG_TUPLE (   locktag,
  dboid,
  reloid,
  blocknum,
  offnum 
)
Value:
((locktag).locktag_field1 = (dboid), \
(locktag).locktag_field2 = (reloid), \
(locktag).locktag_field3 = (blocknum), \
(locktag).locktag_field4 = (offnum), \
(locktag).locktag_type = LOCKTAG_TUPLE, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 219 of file lock.h.

◆ SET_LOCKTAG_VIRTUALTRANSACTION

#define SET_LOCKTAG_VIRTUALTRANSACTION (   locktag,
  vxid 
)
Value:
((locktag).locktag_field1 = (vxid).procNumber, \
(locktag).locktag_field2 = (vxid).localTransactionId, \
(locktag).locktag_field3 = 0, \
(locktag).locktag_field4 = 0, \
(locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \
(locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD)

Definition at line 237 of file lock.h.

◆ SetInvalidVirtualTransactionId

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

Definition at line 76 of file lock.h.

◆ USER_LOCKMETHOD

#define USER_LOCKMETHOD   2

Definition at line 128 of file lock.h.

◆ VirtualTransactionIdEquals

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

Definition at line 73 of file lock.h.

◆ VirtualTransactionIdIsRecoveredPreparedXact

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

Definition at line 71 of file lock.h.

◆ VirtualTransactionIdIsValid

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

Definition at line 69 of file lock.h.

Typedef Documentation

◆ BlockedProcData

◆ BlockedProcsData

◆ LOCALLOCK

◆ LOCALLOCKOWNER

◆ LOCALLOCKTAG

◆ LOCK

◆ LockData

◆ LockInstanceData

◆ LockMethod

Definition at line 118 of file lock.h.

◆ LockMethodData

◆ LOCKMETHODID

Definition at line 124 of file lock.h.

◆ LOCKTAG

◆ LockTagType

◆ PGPROC

Definition at line 30 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 510 of file lock.h.

511{
512 DS_NOT_YET_CHECKED, /* no deadlock check has run yet */
513 DS_NO_DEADLOCK, /* no deadlock detected */
514 DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */
515 DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */
516 DS_BLOCKED_BY_AUTOVACUUM, /* no deadlock; queue blocked by autovacuum
517 * worker */

◆ LockAcquireResult

Enumerator
LOCKACQUIRE_NOT_AVAIL 
LOCKACQUIRE_OK 
LOCKACQUIRE_ALREADY_HELD 
LOCKACQUIRE_ALREADY_CLEAR 

Definition at line 501 of file lock.h.

502{
503 LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
504 LOCKACQUIRE_OK, /* lock successfully acquired */
505 LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */
506 LOCKACQUIRE_ALREADY_CLEAR, /* incremented count for lock already clear */

◆ LockTagType

Enumerator
LOCKTAG_RELATION 
LOCKTAG_RELATION_EXTEND 
LOCKTAG_DATABASE_FROZEN_IDS 
LOCKTAG_PAGE 
LOCKTAG_TUPLE 
LOCKTAG_TRANSACTION 
LOCKTAG_VIRTUALTRANSACTION 
LOCKTAG_SPECULATIVE_TOKEN 
LOCKTAG_OBJECT 
LOCKTAG_USERLOCK 
LOCKTAG_ADVISORY 
LOCKTAG_APPLY_TRANSACTION 

Definition at line 137 of file lock.h.

138{
139 LOCKTAG_RELATION, /* whole relation */
140 LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */
141 LOCKTAG_DATABASE_FROZEN_IDS, /* pg_database.datfrozenxid */
142 LOCKTAG_PAGE, /* one page of a relation */
143 LOCKTAG_TUPLE, /* one physical tuple */
144 LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */
145 LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */
146 LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */
147 LOCKTAG_OBJECT, /* non-relation database object */
148 LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */
149 LOCKTAG_ADVISORY, /* advisory user locks */
150 LOCKTAG_APPLY_TRANSACTION, /* transaction being applied on a logical
151 * replication subscriber */

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:873
#define FastPathStrongLockHashPartition(hashcode)
Definition lock.c:303
static volatile FastPathStrongRelationLockData * FastPathStrongRelationLocks
Definition lock.c:312
static LOCALLOCK * StrongLockInProgress
Definition lock.c:327
#define SpinLockRelease(lock)
Definition spin.h:61
#define SpinLockAcquire(lock)
Definition spin.h:59
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:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#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 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:1271
#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++)
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:1745
PGPROC ** procs
Definition deadlock.c:60
LOCK * lock
Definition deadlock.c:59
int nProcs
Definition deadlock.c:61
static struct link * links
Definition zic.c:302

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, links, 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
int errdetail_internal(const char *fmt,...)
Definition elog.c:1243
int errhint(const char *fmt,...)
Definition elog.c:1330
int errdetail_log(const char *fmt,...)
Definition elog.c:1264
#define _(x)
Definition elog.c:91
void DescribeLockTag(StringInfo buf, const LOCKTAG *tag)
Definition lmgr.c:1249
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4253
#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

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:86

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:531
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
#define NUM_LOCK_PARTITIONS
Definition lwlock.h:95
@ LW_SHARED
Definition lwlock.h:113
const void * data
PGPROC * BackendPidGetProcWithLock(int pid)
Definition procarray.c:3182
dlist_head lockGroupMembers
Definition proc.h:328
PGPROC * lockGroupLeader
Definition proc.h:327
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:803
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:69
#define LockHashPartitionLock(hashcode)
Definition lock.h:528
#define GET_VXID_FROM_PGPROC(vxid_dst, proc)
Definition lock.h:79
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition lock.h:73
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:446
#define FP_LOCK_SLOTS_PER_GROUP
Definition proc.h:92
PGPROC * MyProc
Definition proc.c:67
PROC_HDR * ProcGlobal
Definition proc.c:79
LWLock fpInfoLock
Definition proc.h:316
Oid * fpRelId
Definition proc.h:318
Oid databaseId
Definition proc.h:224
uint64 * fpLockBits
Definition proc.h:317
uint32 allProcCount
Definition proc.h:412
int max_prepared_xacts
Definition twophase.c:116
#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:326

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 SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid)
Definition lock.h:237
#define SET_LOCKTAG_RELATION(locktag, dboid, reloid)
Definition lock.h:183
#define NoLock
Definition lockdefs.h:34
#define ExclusiveLock
Definition lockdefs.h:42
void * repalloc(void *pointer, Size size)
Definition mcxt.c:1632
LocalTransactionId lxid
Definition proc.h:217
pg_atomic_uint64 waitStart
Definition proc.h:260
bool fpVXIDLock
Definition proc.h:319
ProcNumber procNumber
Definition proc.h:212
int pid
Definition proc.h:199
struct PGPROC::@131 vxid
LOCK * waitLock
Definition proc.h:255
LOCKMODE waitLockMode
Definition proc.h:257
LocalTransactionId fpLocalTransactionId
Definition proc.h:320
LocalTransactionId localTransactionId
Definition lock.h:64
ProcNumber procNumber
Definition lock.h:63

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

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

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 144 of file deadlock.c.

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

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

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

4572{
4574 PGPROC *proc = TwoPhaseGetDummyProc(fxid, true);
4575 LOCKTAG *locktag;
4578
4579 Assert(len == sizeof(TwoPhaseLockRecord));
4580 locktag = &rec->locktag;
4582
4584 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4586
4587 LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
4588}
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:923

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

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

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

4540{
4542 LOCKTAG *locktag;
4543 LOCKMODE lockmode;
4545
4546 Assert(len == sizeof(TwoPhaseLockRecord));
4547 locktag = &rec->locktag;
4548 lockmode = rec->lockmode;
4550
4552 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4553
4554 if (lockmode == AccessExclusiveLock &&
4555 locktag->locktag_type == LOCKTAG_RELATION)
4556 {
4558 locktag->locktag_field1 /* dboid */ ,
4559 locktag->locktag_field2 /* reloid */ );
4560 }
4561}
void StandbyAcquireAccessExclusiveLock(TransactionId xid, Oid dbOid, Oid relOid)
Definition standby.c:986
#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
int errdetail_log_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition elog.c:1285
#define LOG
Definition elog.h:31
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
void pfree(void *pointer)
Definition mcxt.c:1616
static char buf[DEFAULT_XLOG_SEG_SIZE]
ProcWaitStatus
Definition proc.h:140
@ PROC_WAIT_STATUS_OK
Definition proc.h:141
@ PROC_WAIT_STATUS_WAITING
Definition proc.h:142
@ PROC_WAIT_STATUS_ERROR
Definition proc.h:143
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
ProcWaitStatus JoinWaitQueue(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait)
Definition proc.c:1146
void GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf, StringInfo lock_waiters_sbuf, int *lockHoldersNum)
Definition proc.c:1906
void LogAccessExclusiveLockPrepare(void)
Definition standby.c:1449
void LogAccessExclusiveLock(Oid dbOid, Oid relOid)
Definition standby.c:1432
bool RecoveryInProgress(void)
Definition xlog.c:6460
#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:327

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:334
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:389
#define SpinLockInit(lock)
Definition spin.h:57
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:495

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:4643
#define LOCALLOCK_LOCKMETHOD(llock)
Definition lock.h:445
#define LOCALLOCK_LOCKTAG(llock)
Definition lock.h:446

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

4855{
4857 LOCK *lock;
4858 bool found;
4859 uint32 hashcode;
4861 int waiters = 0;
4862
4864 elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4865
4866 hashcode = LockTagHashCode(locktag);
4869
4871 locktag,
4872 hashcode,
4873 HASH_FIND,
4874 &found);
4875 if (found)
4876 {
4877 Assert(lock != NULL);
4878 waiters = lock->nRequested;
4879 }
4881
4882 return waiters;
4883}

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 */
2055 Assert(proc->links.next != NULL);
2056 Assert(waitLock);
2057 Assert(!dclist_is_empty(&waitLock->waitProcs));
2059
2060 /* Remove proc from lock's wait queue */
2061 dclist_delete_from_thoroughly(&waitLock->waitProcs, &proc->links);
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 void dclist_delete_from_thoroughly(dclist_head *head, dlist_node *node)
Definition ilist.h:776
PROCLOCK * waitProcLock
Definition proc.h:256
ProcWaitStatus waitStatus
Definition proc.h:184
dlist_node links
Definition proc.h:180
dlist_node * next
Definition ilist.h:140

References Assert, CleanUpLock(), dclist_delete_from_thoroughly(), dclist_is_empty(), fb(), LOCK::granted, lengthof, PGPROC::links, LOCK_LOCKMETHOD, LOCKBIT_OFF, LockMethods, dlist_node::next, LOCK::nGranted, LOCK::nRequested, PROC_WAIT_STATUS_ERROR, PROC_WAIT_STATUS_WAITING, LOCK::requested, 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 4743 of file lock.c.

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

4644{
4645 bool fastpath;
4646 LocalTransactionId lxid;
4647
4649
4650 /*
4651 * Clean up shared memory state.
4652 */
4654
4655 fastpath = MyProc->fpVXIDLock;
4657 MyProc->fpVXIDLock = false;
4659
4661
4662 /*
4663 * If fpVXIDLock has been cleared without touching fpLocalTransactionId,
4664 * that means someone transferred the lock to the main lock table.
4665 */
4666 if (!fastpath && LocalTransactionIdIsValid(lxid))
4667 {
4669 LOCKTAG locktag;
4670
4671 vxid.procNumber = MyProcNumber;
4672 vxid.localTransactionId = lxid;
4673 SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid);
4674
4676 &locktag, ExclusiveLock, false);
4677 }
4678}
uint32 LocalTransactionId
Definition c.h:668
ProcNumber MyProcNumber
Definition globals.c:90
#define LocalTransactionIdIsValid(lxid)
Definition lock.h:68

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

◆ LockTagTypeNames

PGDLLIMPORT const char* const LockTagTypeNames[]
extern

Definition at line 28 of file lockfuncs.c.

28 {
29 "relation",
30 "extend",
31 "frozenid",
32 "page",
33 "tuple",
34 "transactionid",
35 "virtualxid",
36 "spectoken",
37 "object",
38 "userlock",
39 "advisory",
40 "applytransaction"
41};

Referenced by GetLockNameFromTagType(), and pg_lock_status().

◆ 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