1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * lock.h |
4 | * POSTGRES low-level lock mechanism |
5 | * |
6 | * |
7 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
8 | * Portions Copyright (c) 1994, Regents of the University of California |
9 | * |
10 | * src/include/storage/lock.h |
11 | * |
12 | *------------------------------------------------------------------------- |
13 | */ |
14 | #ifndef LOCK_H_ |
15 | #define LOCK_H_ |
16 | |
17 | #ifdef FRONTEND |
18 | #error "lock.h may not be included from frontend code" |
19 | #endif |
20 | |
21 | #include "storage/lockdefs.h" |
22 | #include "storage/backendid.h" |
23 | #include "storage/lwlock.h" |
24 | #include "storage/shmem.h" |
25 | |
26 | |
27 | /* struct PGPROC is declared in proc.h, but must forward-reference it */ |
28 | typedef struct PGPROC PGPROC; |
29 | |
30 | typedef struct PROC_QUEUE |
31 | { |
32 | SHM_QUEUE links; /* head of list of PGPROC objects */ |
33 | int size; /* number of entries in list */ |
34 | } PROC_QUEUE; |
35 | |
36 | /* GUC variables */ |
37 | extern int max_locks_per_xact; |
38 | |
39 | #ifdef LOCK_DEBUG |
40 | extern int Trace_lock_oidmin; |
41 | extern bool Trace_locks; |
42 | extern bool Trace_userlocks; |
43 | extern int Trace_lock_table; |
44 | extern bool Debug_deadlocks; |
45 | #endif /* LOCK_DEBUG */ |
46 | |
47 | |
48 | /* |
49 | * Top-level transactions are identified by VirtualTransactionIDs comprising |
50 | * the BackendId of the backend running the xact, plus a locally-assigned |
51 | * LocalTransactionId. These are guaranteed unique over the short term, |
52 | * but will be reused after a database restart; hence they should never |
53 | * be stored on disk. |
54 | * |
55 | * Note that struct VirtualTransactionId can not be assumed to be atomically |
56 | * assignable as a whole. However, type LocalTransactionId is assumed to |
57 | * be atomically assignable, and the backend ID doesn't change often enough |
58 | * to be a problem, so we can fetch or assign the two fields separately. |
59 | * We deliberately refrain from using the struct within PGPROC, to prevent |
60 | * coding errors from trying to use struct assignment with it; instead use |
61 | * GET_VXID_FROM_PGPROC(). |
62 | */ |
63 | typedef struct |
64 | { |
65 | BackendId backendId; /* determined at backend startup */ |
66 | LocalTransactionId localTransactionId; /* backend-local transaction id */ |
67 | } VirtualTransactionId; |
68 | |
69 | #define InvalidLocalTransactionId 0 |
70 | #define LocalTransactionIdIsValid(lxid) ((lxid) != InvalidLocalTransactionId) |
71 | #define VirtualTransactionIdIsValid(vxid) \ |
72 | (((vxid).backendId != InvalidBackendId) && \ |
73 | LocalTransactionIdIsValid((vxid).localTransactionId)) |
74 | #define VirtualTransactionIdEquals(vxid1, vxid2) \ |
75 | ((vxid1).backendId == (vxid2).backendId && \ |
76 | (vxid1).localTransactionId == (vxid2).localTransactionId) |
77 | #define SetInvalidVirtualTransactionId(vxid) \ |
78 | ((vxid).backendId = InvalidBackendId, \ |
79 | (vxid).localTransactionId = InvalidLocalTransactionId) |
80 | #define GET_VXID_FROM_PGPROC(vxid, proc) \ |
81 | ((vxid).backendId = (proc).backendId, \ |
82 | (vxid).localTransactionId = (proc).lxid) |
83 | |
84 | /* MAX_LOCKMODES cannot be larger than the # of bits in LOCKMASK */ |
85 | #define MAX_LOCKMODES 10 |
86 | |
87 | #define LOCKBIT_ON(lockmode) (1 << (lockmode)) |
88 | #define LOCKBIT_OFF(lockmode) (~(1 << (lockmode))) |
89 | |
90 | |
91 | /* |
92 | * This data structure defines the locking semantics associated with a |
93 | * "lock method". The semantics specify the meaning of each lock mode |
94 | * (by defining which lock modes it conflicts with). |
95 | * All of this data is constant and is kept in const tables. |
96 | * |
97 | * numLockModes -- number of lock modes (READ,WRITE,etc) that |
98 | * are defined in this lock method. Must be less than MAX_LOCKMODES. |
99 | * |
100 | * conflictTab -- this is an array of bitmasks showing lock |
101 | * mode conflicts. conflictTab[i] is a mask with the j-th bit |
102 | * turned on if lock modes i and j conflict. Lock modes are |
103 | * numbered 1..numLockModes; conflictTab[0] is unused. |
104 | * |
105 | * lockModeNames -- ID strings for debug printouts. |
106 | * |
107 | * trace_flag -- pointer to GUC trace flag for this lock method. (The |
108 | * GUC variable is not constant, but we use "const" here to denote that |
109 | * it can't be changed through this reference.) |
110 | */ |
111 | typedef struct LockMethodData |
112 | { |
113 | int numLockModes; |
114 | const LOCKMASK *conflictTab; |
115 | const char *const *lockModeNames; |
116 | const bool *trace_flag; |
117 | } LockMethodData; |
118 | |
119 | typedef const LockMethodData *LockMethod; |
120 | |
121 | /* |
122 | * Lock methods are identified by LOCKMETHODID. (Despite the declaration as |
123 | * uint16, we are constrained to 256 lockmethods by the layout of LOCKTAG.) |
124 | */ |
125 | typedef uint16 LOCKMETHODID; |
126 | |
127 | /* These identify the known lock methods */ |
128 | #define DEFAULT_LOCKMETHOD 1 |
129 | #define USER_LOCKMETHOD 2 |
130 | |
131 | /* |
132 | * LOCKTAG is the key information needed to look up a LOCK item in the |
133 | * lock hashtable. A LOCKTAG value uniquely identifies a lockable object. |
134 | * |
135 | * The LockTagType enum defines the different kinds of objects we can lock. |
136 | * We can handle up to 256 different LockTagTypes. |
137 | */ |
138 | typedef enum LockTagType |
139 | { |
140 | LOCKTAG_RELATION, /* whole relation */ |
141 | LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */ |
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 | } LockTagType; |
151 | |
152 | #define LOCKTAG_LAST_TYPE LOCKTAG_ADVISORY |
153 | |
154 | extern const char *const LockTagTypeNames[]; |
155 | |
156 | /* |
157 | * The LOCKTAG struct is defined with malice aforethought to fit into 16 |
158 | * bytes with no padding. Note that this would need adjustment if we were |
159 | * to widen Oid, BlockNumber, or TransactionId to more than 32 bits. |
160 | * |
161 | * We include lockmethodid in the locktag so that a single hash table in |
162 | * shared memory can store locks of different lockmethods. |
163 | */ |
164 | typedef struct LOCKTAG |
165 | { |
166 | uint32 locktag_field1; /* a 32-bit ID field */ |
167 | uint32 locktag_field2; /* a 32-bit ID field */ |
168 | uint32 locktag_field3; /* a 32-bit ID field */ |
169 | uint16 locktag_field4; /* a 16-bit ID field */ |
170 | uint8 locktag_type; /* see enum LockTagType */ |
171 | uint8 locktag_lockmethodid; /* lockmethod indicator */ |
172 | } LOCKTAG; |
173 | |
174 | /* |
175 | * These macros define how we map logical IDs of lockable objects into |
176 | * the physical fields of LOCKTAG. Use these to set up LOCKTAG values, |
177 | * rather than accessing the fields directly. Note multiple eval of target! |
178 | */ |
179 | |
180 | /* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */ |
181 | #define SET_LOCKTAG_RELATION(locktag,dboid,reloid) \ |
182 | ((locktag).locktag_field1 = (dboid), \ |
183 | (locktag).locktag_field2 = (reloid), \ |
184 | (locktag).locktag_field3 = 0, \ |
185 | (locktag).locktag_field4 = 0, \ |
186 | (locktag).locktag_type = LOCKTAG_RELATION, \ |
187 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
188 | |
189 | /* same ID info as RELATION */ |
190 | #define SET_LOCKTAG_RELATION_EXTEND(locktag,dboid,reloid) \ |
191 | ((locktag).locktag_field1 = (dboid), \ |
192 | (locktag).locktag_field2 = (reloid), \ |
193 | (locktag).locktag_field3 = 0, \ |
194 | (locktag).locktag_field4 = 0, \ |
195 | (locktag).locktag_type = LOCKTAG_RELATION_EXTEND, \ |
196 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
197 | |
198 | /* ID info for a page is RELATION info + BlockNumber */ |
199 | #define SET_LOCKTAG_PAGE(locktag,dboid,reloid,blocknum) \ |
200 | ((locktag).locktag_field1 = (dboid), \ |
201 | (locktag).locktag_field2 = (reloid), \ |
202 | (locktag).locktag_field3 = (blocknum), \ |
203 | (locktag).locktag_field4 = 0, \ |
204 | (locktag).locktag_type = LOCKTAG_PAGE, \ |
205 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
206 | |
207 | /* ID info for a tuple is PAGE info + OffsetNumber */ |
208 | #define SET_LOCKTAG_TUPLE(locktag,dboid,reloid,blocknum,offnum) \ |
209 | ((locktag).locktag_field1 = (dboid), \ |
210 | (locktag).locktag_field2 = (reloid), \ |
211 | (locktag).locktag_field3 = (blocknum), \ |
212 | (locktag).locktag_field4 = (offnum), \ |
213 | (locktag).locktag_type = LOCKTAG_TUPLE, \ |
214 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
215 | |
216 | /* ID info for a transaction is its TransactionId */ |
217 | #define SET_LOCKTAG_TRANSACTION(locktag,xid) \ |
218 | ((locktag).locktag_field1 = (xid), \ |
219 | (locktag).locktag_field2 = 0, \ |
220 | (locktag).locktag_field3 = 0, \ |
221 | (locktag).locktag_field4 = 0, \ |
222 | (locktag).locktag_type = LOCKTAG_TRANSACTION, \ |
223 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
224 | |
225 | /* ID info for a virtual transaction is its VirtualTransactionId */ |
226 | #define SET_LOCKTAG_VIRTUALTRANSACTION(locktag,vxid) \ |
227 | ((locktag).locktag_field1 = (vxid).backendId, \ |
228 | (locktag).locktag_field2 = (vxid).localTransactionId, \ |
229 | (locktag).locktag_field3 = 0, \ |
230 | (locktag).locktag_field4 = 0, \ |
231 | (locktag).locktag_type = LOCKTAG_VIRTUALTRANSACTION, \ |
232 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
233 | |
234 | /* |
235 | * ID info for a speculative insert is TRANSACTION info + |
236 | * its speculative insert counter. |
237 | */ |
238 | #define SET_LOCKTAG_SPECULATIVE_INSERTION(locktag,xid,token) \ |
239 | ((locktag).locktag_field1 = (xid), \ |
240 | (locktag).locktag_field2 = (token), \ |
241 | (locktag).locktag_field3 = 0, \ |
242 | (locktag).locktag_field4 = 0, \ |
243 | (locktag).locktag_type = LOCKTAG_SPECULATIVE_TOKEN, \ |
244 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
245 | |
246 | /* |
247 | * ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID |
248 | * |
249 | * Note: object ID has same representation as in pg_depend and |
250 | * pg_description, but notice that we are constraining SUBID to 16 bits. |
251 | * Also, we use DB OID = 0 for shared objects such as tablespaces. |
252 | */ |
253 | #define SET_LOCKTAG_OBJECT(locktag,dboid,classoid,objoid,objsubid) \ |
254 | ((locktag).locktag_field1 = (dboid), \ |
255 | (locktag).locktag_field2 = (classoid), \ |
256 | (locktag).locktag_field3 = (objoid), \ |
257 | (locktag).locktag_field4 = (objsubid), \ |
258 | (locktag).locktag_type = LOCKTAG_OBJECT, \ |
259 | (locktag).locktag_lockmethodid = DEFAULT_LOCKMETHOD) |
260 | |
261 | #define SET_LOCKTAG_ADVISORY(locktag,id1,id2,id3,id4) \ |
262 | ((locktag).locktag_field1 = (id1), \ |
263 | (locktag).locktag_field2 = (id2), \ |
264 | (locktag).locktag_field3 = (id3), \ |
265 | (locktag).locktag_field4 = (id4), \ |
266 | (locktag).locktag_type = LOCKTAG_ADVISORY, \ |
267 | (locktag).locktag_lockmethodid = USER_LOCKMETHOD) |
268 | |
269 | |
270 | /* |
271 | * Per-locked-object lock information: |
272 | * |
273 | * tag -- uniquely identifies the object being locked |
274 | * grantMask -- bitmask for all lock types currently granted on this object. |
275 | * waitMask -- bitmask for all lock types currently awaited on this object. |
276 | * procLocks -- list of PROCLOCK objects for this lock. |
277 | * waitProcs -- queue of processes waiting for this lock. |
278 | * requested -- count of each lock type currently requested on the lock |
279 | * (includes requests already granted!!). |
280 | * nRequested -- total requested locks of all types. |
281 | * granted -- count of each lock type currently granted on the lock. |
282 | * nGranted -- total granted locks of all types. |
283 | * |
284 | * Note: these counts count 1 for each backend. Internally to a backend, |
285 | * there may be multiple grabs on a particular lock, but this is not reflected |
286 | * into shared memory. |
287 | */ |
288 | typedef struct LOCK |
289 | { |
290 | /* hash key */ |
291 | LOCKTAG tag; /* unique identifier of lockable object */ |
292 | |
293 | /* data */ |
294 | LOCKMASK grantMask; /* bitmask for lock types already granted */ |
295 | LOCKMASK waitMask; /* bitmask for lock types awaited */ |
296 | SHM_QUEUE procLocks; /* list of PROCLOCK objects assoc. with lock */ |
297 | PROC_QUEUE waitProcs; /* list of PGPROC objects waiting on lock */ |
298 | int requested[MAX_LOCKMODES]; /* counts of requested locks */ |
299 | int nRequested; /* total of requested[] array */ |
300 | int granted[MAX_LOCKMODES]; /* counts of granted locks */ |
301 | int nGranted; /* total of granted[] array */ |
302 | } LOCK; |
303 | |
304 | #define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid) |
305 | |
306 | |
307 | /* |
308 | * We may have several different backends holding or awaiting locks |
309 | * on the same lockable object. We need to store some per-holder/waiter |
310 | * information for each such holder (or would-be holder). This is kept in |
311 | * a PROCLOCK struct. |
312 | * |
313 | * PROCLOCKTAG is the key information needed to look up a PROCLOCK item in the |
314 | * proclock hashtable. A PROCLOCKTAG value uniquely identifies the combination |
315 | * of a lockable object and a holder/waiter for that object. (We can use |
316 | * pointers here because the PROCLOCKTAG need only be unique for the lifespan |
317 | * of the PROCLOCK, and it will never outlive the lock or the proc.) |
318 | * |
319 | * Internally to a backend, it is possible for the same lock to be held |
320 | * for different purposes: the backend tracks transaction locks separately |
321 | * from session locks. However, this is not reflected in the shared-memory |
322 | * state: we only track which backend(s) hold the lock. This is OK since a |
323 | * backend can never block itself. |
324 | * |
325 | * The holdMask field shows the already-granted locks represented by this |
326 | * proclock. Note that there will be a proclock object, possibly with |
327 | * zero holdMask, for any lock that the process is currently waiting on. |
328 | * Otherwise, proclock objects whose holdMasks are zero are recycled |
329 | * as soon as convenient. |
330 | * |
331 | * releaseMask is workspace for LockReleaseAll(): it shows the locks due |
332 | * to be released during the current call. This must only be examined or |
333 | * set by the backend owning the PROCLOCK. |
334 | * |
335 | * Each PROCLOCK object is linked into lists for both the associated LOCK |
336 | * object and the owning PGPROC object. Note that the PROCLOCK is entered |
337 | * into these lists as soon as it is created, even if no lock has yet been |
338 | * granted. A PGPROC that is waiting for a lock to be granted will also be |
339 | * linked into the lock's waitProcs queue. |
340 | */ |
341 | typedef struct PROCLOCKTAG |
342 | { |
343 | /* NB: we assume this struct contains no padding! */ |
344 | LOCK *myLock; /* link to per-lockable-object information */ |
345 | PGPROC *myProc; /* link to PGPROC of owning backend */ |
346 | } PROCLOCKTAG; |
347 | |
348 | typedef struct PROCLOCK |
349 | { |
350 | /* tag */ |
351 | PROCLOCKTAG tag; /* unique identifier of proclock object */ |
352 | |
353 | /* data */ |
354 | PGPROC *groupLeader; /* proc's lock group leader, or proc itself */ |
355 | LOCKMASK holdMask; /* bitmask for lock types currently held */ |
356 | LOCKMASK releaseMask; /* bitmask for lock types to be released */ |
357 | SHM_QUEUE lockLink; /* list link in LOCK's list of proclocks */ |
358 | SHM_QUEUE procLink; /* list link in PGPROC's list of proclocks */ |
359 | } PROCLOCK; |
360 | |
361 | #define PROCLOCK_LOCKMETHOD(proclock) \ |
362 | LOCK_LOCKMETHOD(*((proclock).tag.myLock)) |
363 | |
364 | /* |
365 | * Each backend also maintains a local hash table with information about each |
366 | * lock it is currently interested in. In particular the local table counts |
367 | * the number of times that lock has been acquired. This allows multiple |
368 | * requests for the same lock to be executed without additional accesses to |
369 | * shared memory. We also track the number of lock acquisitions per |
370 | * ResourceOwner, so that we can release just those locks belonging to a |
371 | * particular ResourceOwner. |
372 | * |
373 | * When holding a lock taken "normally", the lock and proclock fields always |
374 | * point to the associated objects in shared memory. However, if we acquired |
375 | * the lock via the fast-path mechanism, the lock and proclock fields are set |
376 | * to NULL, since there probably aren't any such objects in shared memory. |
377 | * (If the lock later gets promoted to normal representation, we may eventually |
378 | * update our locallock's lock/proclock fields after finding the shared |
379 | * objects.) |
380 | * |
381 | * Caution: a locallock object can be left over from a failed lock acquisition |
382 | * attempt. In this case its lock/proclock fields are untrustworthy, since |
383 | * the shared lock object is neither held nor awaited, and hence is available |
384 | * to be reclaimed. If nLocks > 0 then these pointers must either be valid or |
385 | * NULL, but when nLocks == 0 they should be considered garbage. |
386 | */ |
387 | typedef struct LOCALLOCKTAG |
388 | { |
389 | LOCKTAG lock; /* identifies the lockable object */ |
390 | LOCKMODE mode; /* lock mode for this table entry */ |
391 | } LOCALLOCKTAG; |
392 | |
393 | typedef struct LOCALLOCKOWNER |
394 | { |
395 | /* |
396 | * Note: if owner is NULL then the lock is held on behalf of the session; |
397 | * otherwise it is held on behalf of my current transaction. |
398 | * |
399 | * Must use a forward struct reference to avoid circularity. |
400 | */ |
401 | struct ResourceOwnerData *owner; |
402 | int64 nLocks; /* # of times held by this owner */ |
403 | } LOCALLOCKOWNER; |
404 | |
405 | typedef struct LOCALLOCK |
406 | { |
407 | /* tag */ |
408 | LOCALLOCKTAG tag; /* unique identifier of locallock entry */ |
409 | |
410 | /* data */ |
411 | uint32 hashcode; /* copy of LOCKTAG's hash value */ |
412 | LOCK *lock; /* associated LOCK object, if any */ |
413 | PROCLOCK *proclock; /* associated PROCLOCK object, if any */ |
414 | int64 nLocks; /* total number of times lock is held */ |
415 | int numLockOwners; /* # of relevant ResourceOwners */ |
416 | int maxLockOwners; /* allocated size of array */ |
417 | LOCALLOCKOWNER *lockOwners; /* dynamically resizable array */ |
418 | bool holdsStrongLockCount; /* bumped FastPathStrongRelationLocks */ |
419 | bool lockCleared; /* we read all sinval msgs for lock */ |
420 | } LOCALLOCK; |
421 | |
422 | #define LOCALLOCK_LOCKMETHOD(llock) ((llock).tag.lock.locktag_lockmethodid) |
423 | |
424 | |
425 | /* |
426 | * These structures hold information passed from lmgr internals to the lock |
427 | * listing user-level functions (in lockfuncs.c). |
428 | */ |
429 | |
430 | typedef struct LockInstanceData |
431 | { |
432 | LOCKTAG locktag; /* tag for locked object */ |
433 | LOCKMASK holdMask; /* locks held by this PGPROC */ |
434 | LOCKMODE waitLockMode; /* lock awaited by this PGPROC, if any */ |
435 | BackendId backend; /* backend ID of this PGPROC */ |
436 | LocalTransactionId lxid; /* local transaction ID of this PGPROC */ |
437 | int pid; /* pid of this PGPROC */ |
438 | int leaderPid; /* pid of group leader; = pid if no group */ |
439 | bool fastpath; /* taken via fastpath? */ |
440 | } LockInstanceData; |
441 | |
442 | typedef struct LockData |
443 | { |
444 | int nelements; /* The length of the array */ |
445 | LockInstanceData *locks; /* Array of per-PROCLOCK information */ |
446 | } LockData; |
447 | |
448 | typedef struct BlockedProcData |
449 | { |
450 | int pid; /* pid of a blocked PGPROC */ |
451 | /* Per-PROCLOCK information about PROCLOCKs of the lock the pid awaits */ |
452 | /* (these fields refer to indexes in BlockedProcsData.locks[]) */ |
453 | int first_lock; /* index of first relevant LockInstanceData */ |
454 | int num_locks; /* number of relevant LockInstanceDatas */ |
455 | /* PIDs of PGPROCs that are ahead of "pid" in the lock's wait queue */ |
456 | /* (these fields refer to indexes in BlockedProcsData.waiter_pids[]) */ |
457 | int first_waiter; /* index of first preceding waiter */ |
458 | int num_waiters; /* number of preceding waiters */ |
459 | } BlockedProcData; |
460 | |
461 | typedef struct BlockedProcsData |
462 | { |
463 | BlockedProcData *procs; /* Array of per-blocked-proc information */ |
464 | LockInstanceData *locks; /* Array of per-PROCLOCK information */ |
465 | int *waiter_pids; /* Array of PIDs of other blocked PGPROCs */ |
466 | int nprocs; /* # of valid entries in procs[] array */ |
467 | int maxprocs; /* Allocated length of procs[] array */ |
468 | int nlocks; /* # of valid entries in locks[] array */ |
469 | int maxlocks; /* Allocated length of locks[] array */ |
470 | int npids; /* # of valid entries in waiter_pids[] array */ |
471 | int maxpids; /* Allocated length of waiter_pids[] array */ |
472 | } BlockedProcsData; |
473 | |
474 | |
475 | /* Result codes for LockAcquire() */ |
476 | typedef enum |
477 | { |
478 | LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */ |
479 | LOCKACQUIRE_OK, /* lock successfully acquired */ |
480 | LOCKACQUIRE_ALREADY_HELD, /* incremented count for lock already held */ |
481 | LOCKACQUIRE_ALREADY_CLEAR /* incremented count for lock already clear */ |
482 | } LockAcquireResult; |
483 | |
484 | /* Deadlock states identified by DeadLockCheck() */ |
485 | typedef enum |
486 | { |
487 | DS_NOT_YET_CHECKED, /* no deadlock check has run yet */ |
488 | DS_NO_DEADLOCK, /* no deadlock detected */ |
489 | DS_SOFT_DEADLOCK, /* deadlock avoided by queue rearrangement */ |
490 | DS_HARD_DEADLOCK, /* deadlock, no way out but ERROR */ |
491 | DS_BLOCKED_BY_AUTOVACUUM /* no deadlock; queue blocked by autovacuum |
492 | * worker */ |
493 | } DeadLockState; |
494 | |
495 | /* |
496 | * The lockmgr's shared hash tables are partitioned to reduce contention. |
497 | * To determine which partition a given locktag belongs to, compute the tag's |
498 | * hash code with LockTagHashCode(), then apply one of these macros. |
499 | * NB: NUM_LOCK_PARTITIONS must be a power of 2! |
500 | */ |
501 | #define LockHashPartition(hashcode) \ |
502 | ((hashcode) % NUM_LOCK_PARTITIONS) |
503 | #define LockHashPartitionLock(hashcode) \ |
504 | (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + \ |
505 | LockHashPartition(hashcode)].lock) |
506 | #define LockHashPartitionLockByIndex(i) \ |
507 | (&MainLWLockArray[LOCK_MANAGER_LWLOCK_OFFSET + (i)].lock) |
508 | |
509 | /* |
510 | * The deadlock detector needs to be able to access lockGroupLeader and |
511 | * related fields in the PGPROC, so we arrange for those fields to be protected |
512 | * by one of the lock hash partition locks. Since the deadlock detector |
513 | * acquires all such locks anyway, this makes it safe for it to access these |
514 | * fields without doing anything extra. To avoid contention as much as |
515 | * possible, we map different PGPROCs to different partition locks. The lock |
516 | * used for a given lock group is determined by the group leader's pgprocno. |
517 | */ |
518 | #define LockHashPartitionLockByProc(leader_pgproc) \ |
519 | LockHashPartitionLock((leader_pgproc)->pgprocno) |
520 | |
521 | /* |
522 | * function prototypes |
523 | */ |
524 | extern void InitLocks(void); |
525 | extern LockMethod GetLocksMethodTable(const LOCK *lock); |
526 | extern LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag); |
527 | extern uint32 LockTagHashCode(const LOCKTAG *locktag); |
528 | extern bool DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2); |
529 | extern LockAcquireResult LockAcquire(const LOCKTAG *locktag, |
530 | LOCKMODE lockmode, |
531 | bool sessionLock, |
532 | bool dontWait); |
533 | extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, |
534 | LOCKMODE lockmode, |
535 | bool sessionLock, |
536 | bool dontWait, |
537 | bool reportMemoryError, |
538 | LOCALLOCK **locallockp); |
539 | extern void AbortStrongLockAcquire(void); |
540 | extern void MarkLockClear(LOCALLOCK *locallock); |
541 | extern bool LockRelease(const LOCKTAG *locktag, |
542 | LOCKMODE lockmode, bool sessionLock); |
543 | extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks); |
544 | extern void LockReleaseSession(LOCKMETHODID lockmethodid); |
545 | extern void LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks); |
546 | extern void LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks); |
547 | extern bool LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode); |
548 | extern bool LockHasWaiters(const LOCKTAG *locktag, |
549 | LOCKMODE lockmode, bool sessionLock); |
550 | extern VirtualTransactionId *GetLockConflicts(const LOCKTAG *locktag, |
551 | LOCKMODE lockmode, int *countp); |
552 | extern void AtPrepare_Locks(void); |
553 | extern void PostPrepare_Locks(TransactionId xid); |
554 | extern int LockCheckConflicts(LockMethod lockMethodTable, |
555 | LOCKMODE lockmode, |
556 | LOCK *lock, PROCLOCK *proclock); |
557 | extern void GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode); |
558 | extern void GrantAwaitedLock(void); |
559 | extern void RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode); |
560 | extern Size LockShmemSize(void); |
561 | extern LockData *GetLockStatusData(void); |
562 | extern BlockedProcsData *GetBlockerStatusData(int blocked_pid); |
563 | |
564 | extern xl_standby_lock *GetRunningTransactionLocks(int *nlocks); |
565 | extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode); |
566 | |
567 | extern void lock_twophase_recover(TransactionId xid, uint16 info, |
568 | void *recdata, uint32 len); |
569 | extern void lock_twophase_postcommit(TransactionId xid, uint16 info, |
570 | void *recdata, uint32 len); |
571 | extern void lock_twophase_postabort(TransactionId xid, uint16 info, |
572 | void *recdata, uint32 len); |
573 | extern void lock_twophase_standby_recover(TransactionId xid, uint16 info, |
574 | void *recdata, uint32 len); |
575 | |
576 | extern DeadLockState DeadLockCheck(PGPROC *proc); |
577 | extern PGPROC *GetBlockingAutoVacuumPgproc(void); |
578 | extern void DeadLockReport(void) pg_attribute_noreturn(); |
579 | extern void RememberSimpleDeadLock(PGPROC *proc1, |
580 | LOCKMODE lockmode, |
581 | LOCK *lock, |
582 | PGPROC *proc2); |
583 | extern void InitDeadLockChecking(void); |
584 | |
585 | extern int LockWaiterCount(const LOCKTAG *locktag); |
586 | |
587 | #ifdef LOCK_DEBUG |
588 | extern void DumpLocks(PGPROC *proc); |
589 | extern void DumpAllLocks(void); |
590 | #endif |
591 | |
592 | /* Lock a VXID (used to wait for a transaction to finish) */ |
593 | extern void VirtualXactLockTableInsert(VirtualTransactionId vxid); |
594 | extern void VirtualXactLockTableCleanup(void); |
595 | extern bool VirtualXactLock(VirtualTransactionId vxid, bool wait); |
596 | |
597 | #endif /* LOCK_H */ |
598 | |