Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * lock.c
4 : * POSTGRES primary lock mechanism
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/storage/lmgr/lock.c
12 : *
13 : * NOTES
14 : * A lock table is a shared memory hash table. When
15 : * a process tries to acquire a lock of a type that conflicts
16 : * with existing locks, it is put to sleep using the routines
17 : * in storage/lmgr/proc.c.
18 : *
19 : * For the most part, this code should be invoked via lmgr.c
20 : * or another lock-management module, not directly.
21 : *
22 : * Interface:
23 : *
24 : * InitLocks(), GetLocksMethodTable(), GetLockTagsMethodTable(),
25 : * LockAcquire(), LockRelease(), LockReleaseAll(),
26 : * LockCheckConflicts(), GrantLock()
27 : *
28 : *-------------------------------------------------------------------------
29 : */
30 : #include "postgres.h"
31 :
32 : #include <signal.h>
33 : #include <unistd.h>
34 :
35 : #include "access/transam.h"
36 : #include "access/twophase.h"
37 : #include "access/twophase_rmgr.h"
38 : #include "access/xact.h"
39 : #include "access/xlog.h"
40 : #include "access/xlogutils.h"
41 : #include "miscadmin.h"
42 : #include "pg_trace.h"
43 : #include "pgstat.h"
44 : #include "storage/proc.h"
45 : #include "storage/procarray.h"
46 : #include "storage/sinvaladt.h"
47 : #include "storage/spin.h"
48 : #include "storage/standby.h"
49 : #include "utils/memutils.h"
50 : #include "utils/ps_status.h"
51 : #include "utils/resowner_private.h"
52 :
53 :
54 : /* This configuration variable is used to set the lock table size */
55 : int max_locks_per_xact; /* set by guc.c */
56 :
57 : #define NLOCKENTS() \
58 : mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
59 :
60 :
61 : /*
62 : * Data structures defining the semantics of the standard lock methods.
63 : *
64 : * The conflict table defines the semantics of the various lock modes.
65 : */
66 : static const LOCKMASK LockConflicts[] = {
67 : 0,
68 :
69 : /* AccessShareLock */
70 : LOCKBIT_ON(AccessExclusiveLock),
71 :
72 : /* RowShareLock */
73 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock),
74 :
75 : /* RowExclusiveLock */
76 : LOCKBIT_ON(ShareLock) | LOCKBIT_ON(ShareRowExclusiveLock) |
77 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock),
78 :
79 : /* ShareUpdateExclusiveLock */
80 : LOCKBIT_ON(ShareUpdateExclusiveLock) |
81 : LOCKBIT_ON(ShareLock) | LOCKBIT_ON(ShareRowExclusiveLock) |
82 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock),
83 :
84 : /* ShareLock */
85 : LOCKBIT_ON(RowExclusiveLock) | LOCKBIT_ON(ShareUpdateExclusiveLock) |
86 : LOCKBIT_ON(ShareRowExclusiveLock) |
87 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock),
88 :
89 : /* ShareRowExclusiveLock */
90 : LOCKBIT_ON(RowExclusiveLock) | LOCKBIT_ON(ShareUpdateExclusiveLock) |
91 : LOCKBIT_ON(ShareLock) | LOCKBIT_ON(ShareRowExclusiveLock) |
92 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock),
93 :
94 : /* ExclusiveLock */
95 : LOCKBIT_ON(RowShareLock) |
96 : LOCKBIT_ON(RowExclusiveLock) | LOCKBIT_ON(ShareUpdateExclusiveLock) |
97 : LOCKBIT_ON(ShareLock) | LOCKBIT_ON(ShareRowExclusiveLock) |
98 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock),
99 :
100 : /* AccessExclusiveLock */
101 : LOCKBIT_ON(AccessShareLock) | LOCKBIT_ON(RowShareLock) |
102 : LOCKBIT_ON(RowExclusiveLock) | LOCKBIT_ON(ShareUpdateExclusiveLock) |
103 : LOCKBIT_ON(ShareLock) | LOCKBIT_ON(ShareRowExclusiveLock) |
104 : LOCKBIT_ON(ExclusiveLock) | LOCKBIT_ON(AccessExclusiveLock)
105 :
106 : };
107 :
108 : /* Names of lock modes, for debug printouts */
109 : static const char *const lock_mode_names[] =
110 : {
111 : "INVALID",
112 : "AccessShareLock",
113 : "RowShareLock",
114 : "RowExclusiveLock",
115 : "ShareUpdateExclusiveLock",
116 : "ShareLock",
117 : "ShareRowExclusiveLock",
118 : "ExclusiveLock",
119 : "AccessExclusiveLock"
120 : };
121 :
122 : #ifndef LOCK_DEBUG
123 : static bool Dummy_trace = false;
124 : #endif
125 :
126 : static const LockMethodData default_lockmethod = {
127 : MaxLockMode,
128 : LockConflicts,
129 : lock_mode_names,
130 : #ifdef LOCK_DEBUG
131 : &Trace_locks
132 : #else
133 : &Dummy_trace
134 : #endif
135 : };
136 :
137 : static const LockMethodData user_lockmethod = {
138 : MaxLockMode,
139 : LockConflicts,
140 : lock_mode_names,
141 : #ifdef LOCK_DEBUG
142 : &Trace_userlocks
143 : #else
144 : &Dummy_trace
145 : #endif
146 : };
147 :
148 : /*
149 : * map from lock method id to the lock table data structures
150 : */
151 : static const LockMethod LockMethods[] = {
152 : NULL,
153 : &default_lockmethod,
154 : &user_lockmethod
155 : };
156 :
157 :
158 : /* Record that's written to 2PC state file when a lock is persisted */
159 : typedef struct TwoPhaseLockRecord
160 : {
161 : LOCKTAG locktag;
162 : LOCKMODE lockmode;
163 : } TwoPhaseLockRecord;
164 :
165 :
166 : /*
167 : * Count of the number of fast path lock slots we believe to be used. This
168 : * might be higher than the real number if another backend has transferred
169 : * our locks to the primary lock table, but it can never be lower than the
170 : * real value, since only we can acquire locks on our own behalf.
171 : */
172 : static int FastPathLocalUseCount = 0;
173 :
174 : /*
175 : * Flag to indicate if the relation extension lock is held by this backend.
176 : * This flag is used to ensure that while holding the relation extension lock
177 : * we don't try to acquire a heavyweight lock on any other object. This
178 : * restriction implies that the relation extension lock won't ever participate
179 : * in the deadlock cycle because we can never wait for any other heavyweight
180 : * lock after acquiring this lock.
181 : *
182 : * Such a restriction is okay for relation extension locks as unlike other
183 : * heavyweight locks these are not held till the transaction end. These are
184 : * taken for a short duration to extend a particular relation and then
185 : * released.
186 : */
187 : static bool IsRelationExtensionLockHeld PG_USED_FOR_ASSERTS_ONLY = false;
188 :
189 : /*
190 : * Flag to indicate if the page lock is held by this backend. We don't
191 : * acquire any other heavyweight lock while holding the page lock except for
192 : * relation extension. However, these locks are never taken in reverse order
193 : * which implies that page locks will also never participate in the deadlock
194 : * cycle.
195 : *
196 : * Similar to relation extension, page locks are also held for a short
197 : * duration, so imposing such a restriction won't hurt.
198 : */
199 : static bool IsPageLockHeld PG_USED_FOR_ASSERTS_ONLY = false;
200 :
201 : /* Macros for manipulating proc->fpLockBits */
202 : #define FAST_PATH_BITS_PER_SLOT 3
203 : #define FAST_PATH_LOCKNUMBER_OFFSET 1
204 : #define FAST_PATH_MASK ((1 << FAST_PATH_BITS_PER_SLOT) - 1)
205 : #define FAST_PATH_GET_BITS(proc, n) \
206 : (((proc)->fpLockBits >> (FAST_PATH_BITS_PER_SLOT * n)) & FAST_PATH_MASK)
207 : #define FAST_PATH_BIT_POSITION(n, l) \
208 : (AssertMacro((l) >= FAST_PATH_LOCKNUMBER_OFFSET), \
209 : AssertMacro((l) < FAST_PATH_BITS_PER_SLOT+FAST_PATH_LOCKNUMBER_OFFSET), \
210 : AssertMacro((n) < FP_LOCK_SLOTS_PER_BACKEND), \
211 : ((l) - FAST_PATH_LOCKNUMBER_OFFSET + FAST_PATH_BITS_PER_SLOT * (n)))
212 : #define FAST_PATH_SET_LOCKMODE(proc, n, l) \
213 : (proc)->fpLockBits |= UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)
214 : #define FAST_PATH_CLEAR_LOCKMODE(proc, n, l) \
215 : (proc)->fpLockBits &= ~(UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l))
216 : #define FAST_PATH_CHECK_LOCKMODE(proc, n, l) \
217 : ((proc)->fpLockBits & (UINT64CONST(1) << FAST_PATH_BIT_POSITION(n, l)))
218 :
219 : /*
220 : * The fast-path lock mechanism is concerned only with relation locks on
221 : * unshared relations by backends bound to a database. The fast-path
222 : * mechanism exists mostly to accelerate acquisition and release of locks
223 : * that rarely conflict. Because ShareUpdateExclusiveLock is
224 : * self-conflicting, it can't use the fast-path mechanism; but it also does
225 : * not conflict with any of the locks that do, so we can ignore it completely.
226 : */
227 : #define EligibleForRelationFastPath(locktag, mode) \
228 : ((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
229 : (locktag)->locktag_type == LOCKTAG_RELATION && \
230 : (locktag)->locktag_field1 == MyDatabaseId && \
231 : MyDatabaseId != InvalidOid && \
232 : (mode) < ShareUpdateExclusiveLock)
233 : #define ConflictsWithRelationFastPath(locktag, mode) \
234 : ((locktag)->locktag_lockmethodid == DEFAULT_LOCKMETHOD && \
235 : (locktag)->locktag_type == LOCKTAG_RELATION && \
236 : (locktag)->locktag_field1 != InvalidOid && \
237 : (mode) > ShareUpdateExclusiveLock)
238 :
239 : static bool FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode);
240 : static bool FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode);
241 : static bool FastPathTransferRelationLocks(LockMethod lockMethodTable,
242 : const LOCKTAG *locktag, uint32 hashcode);
243 : static PROCLOCK *FastPathGetRelationLockEntry(LOCALLOCK *locallock);
244 :
245 : /*
246 : * To make the fast-path lock mechanism work, we must have some way of
247 : * preventing the use of the fast-path when a conflicting lock might be present.
248 : * We partition* the locktag space into FAST_PATH_STRONG_LOCK_HASH_PARTITIONS,
249 : * and maintain an integer count of the number of "strong" lockers
250 : * in each partition. When any "strong" lockers are present (which is
251 : * hopefully not very often), the fast-path mechanism can't be used, and we
252 : * must fall back to the slower method of pushing matching locks directly
253 : * into the main lock tables.
254 : *
255 : * The deadlock detector does not know anything about the fast path mechanism,
256 : * so any locks that might be involved in a deadlock must be transferred from
257 : * the fast-path queues to the main lock table.
258 : */
259 :
260 : #define FAST_PATH_STRONG_LOCK_HASH_BITS 10
261 : #define FAST_PATH_STRONG_LOCK_HASH_PARTITIONS \
262 : (1 << FAST_PATH_STRONG_LOCK_HASH_BITS)
263 : #define FastPathStrongLockHashPartition(hashcode) \
264 : ((hashcode) % FAST_PATH_STRONG_LOCK_HASH_PARTITIONS)
265 :
266 : typedef struct
267 : {
268 : slock_t mutex;
269 : uint32 count[FAST_PATH_STRONG_LOCK_HASH_PARTITIONS];
270 : } FastPathStrongRelationLockData;
271 :
272 : static volatile FastPathStrongRelationLockData *FastPathStrongRelationLocks;
273 :
274 :
275 : /*
276 : * Pointers to hash tables containing lock state
277 : *
278 : * The LockMethodLockHash and LockMethodProcLockHash hash tables are in
279 : * shared memory; LockMethodLocalHash is local to each backend.
280 : */
281 : static HTAB *LockMethodLockHash;
282 : static HTAB *LockMethodProcLockHash;
283 : static HTAB *LockMethodLocalHash;
284 :
285 :
286 : /* private state for error cleanup */
287 : static LOCALLOCK *StrongLockInProgress;
288 : static LOCALLOCK *awaitedLock;
289 : static ResourceOwner awaitedOwner;
290 :
291 :
292 : #ifdef LOCK_DEBUG
293 :
294 : /*------
295 : * The following configuration options are available for lock debugging:
296 : *
297 : * TRACE_LOCKS -- give a bunch of output what's going on in this file
298 : * TRACE_USERLOCKS -- same but for user locks
299 : * TRACE_LOCK_OIDMIN-- do not trace locks for tables below this oid
300 : * (use to avoid output on system tables)
301 : * TRACE_LOCK_TABLE -- trace locks on this table (oid) unconditionally
302 : * DEBUG_DEADLOCKS -- currently dumps locks at untimely occasions ;)
303 : *
304 : * Furthermore, but in storage/lmgr/lwlock.c:
305 : * TRACE_LWLOCKS -- trace lightweight locks (pretty useless)
306 : *
307 : * Define LOCK_DEBUG at compile time to get all these enabled.
308 : * --------
309 : */
310 :
311 : int Trace_lock_oidmin = FirstNormalObjectId;
312 : bool Trace_locks = false;
313 : bool Trace_userlocks = false;
314 : int Trace_lock_table = 0;
315 : bool Debug_deadlocks = false;
316 :
317 :
318 : inline static bool
319 : LOCK_DEBUG_ENABLED(const LOCKTAG *tag)
320 : {
321 : return
322 : (*(LockMethods[tag->locktag_lockmethodid]->trace_flag) &&
323 : ((Oid) tag->locktag_field2 >= (Oid) Trace_lock_oidmin))
324 : || (Trace_lock_table &&
325 : (tag->locktag_field2 == Trace_lock_table));
326 : }
327 :
328 :
329 : inline static void
330 : LOCK_PRINT(const char *where, const LOCK *lock, LOCKMODE type)
331 : {
332 : if (LOCK_DEBUG_ENABLED(&lock->tag))
333 : elog(LOG,
334 : "%s: lock(%p) id(%u,%u,%u,%u,%u,%u) grantMask(%x) "
335 : "req(%d,%d,%d,%d,%d,%d,%d)=%d "
336 : "grant(%d,%d,%d,%d,%d,%d,%d)=%d wait(%d) type(%s)",
337 : where, lock,
338 : lock->tag.locktag_field1, lock->tag.locktag_field2,
339 : lock->tag.locktag_field3, lock->tag.locktag_field4,
340 : lock->tag.locktag_type, lock->tag.locktag_lockmethodid,
341 : lock->grantMask,
342 : lock->requested[1], lock->requested[2], lock->requested[3],
343 : lock->requested[4], lock->requested[5], lock->requested[6],
344 : lock->requested[7], lock->nRequested,
345 : lock->granted[1], lock->granted[2], lock->granted[3],
346 : lock->granted[4], lock->granted[5], lock->granted[6],
347 : lock->granted[7], lock->nGranted,
348 : dclist_count(&lock->waitProcs),
349 : LockMethods[LOCK_LOCKMETHOD(*lock)]->lockModeNames[type]);
350 : }
351 :
352 :
353 : inline static void
354 : PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
355 : {
356 : if (LOCK_DEBUG_ENABLED(&proclockP->tag.myLock->tag))
357 : elog(LOG,
358 : "%s: proclock(%p) lock(%p) method(%u) proc(%p) hold(%x)",
359 : where, proclockP, proclockP->tag.myLock,
360 : PROCLOCK_LOCKMETHOD(*(proclockP)),
361 : proclockP->tag.myProc, (int) proclockP->holdMask);
362 : }
363 : #else /* not LOCK_DEBUG */
364 :
365 : #define LOCK_PRINT(where, lock, type) ((void) 0)
366 : #define PROCLOCK_PRINT(where, proclockP) ((void) 0)
367 : #endif /* not LOCK_DEBUG */
368 :
369 :
370 : static uint32 proclock_hash(const void *key, Size keysize);
371 : static void RemoveLocalLock(LOCALLOCK *locallock);
372 : static PROCLOCK *SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
373 : const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode);
374 : static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
375 : static void BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode);
376 : static void FinishStrongLockAcquire(void);
377 : static void WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner);
378 : static void ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock);
379 : static void LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent);
380 : static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
381 : PROCLOCK *proclock, LockMethod lockMethodTable);
382 : static void CleanUpLock(LOCK *lock, PROCLOCK *proclock,
383 : LockMethod lockMethodTable, uint32 hashcode,
384 : bool wakeupNeeded);
385 : static void LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc,
386 : LOCKTAG *locktag, LOCKMODE lockmode,
387 : bool decrement_strong_lock_count);
388 : static void GetSingleProcBlockerStatusData(PGPROC *blocked_proc,
389 : BlockedProcsData *data);
390 :
391 :
392 : /*
393 : * InitLocks -- Initialize the lock manager's data structures.
394 : *
395 : * This is called from CreateSharedMemoryAndSemaphores(), which see for
396 : * more comments. In the normal postmaster case, the shared hash tables
397 : * are created here, as well as a locallock hash table that will remain
398 : * unused and empty in the postmaster itself. Backends inherit the pointers
399 : * to the shared tables via fork(), and also inherit an image of the locallock
400 : * hash table, which they proceed to use. In the EXEC_BACKEND case, each
401 : * backend re-executes this code to obtain pointers to the already existing
402 : * shared hash tables and to create its locallock hash table.
403 : */
404 : void
8143 tgl 405 CBC 1826 : InitLocks(void)
406 : {
407 : HASHCTL info;
408 : long init_table_size,
409 : max_table_size;
410 : bool found;
411 :
412 : /*
413 : * Compute init/max size to request for lock hashtables. Note these
414 : * calculations must agree with LockShmemSize!
415 : */
6505 416 1826 : max_table_size = NLOCKENTS();
6767 417 1826 : init_table_size = max_table_size / 2;
418 :
419 : /*
420 : * Allocate hash table for LOCK structs. This stores per-locked-object
421 : * information.
422 : */
7860 423 1826 : info.keysize = sizeof(LOCKTAG);
424 1826 : info.entrysize = sizeof(LOCK);
6104 425 1826 : info.num_partitions = NUM_LOCK_PARTITIONS;
426 :
427 1826 : LockMethodLockHash = ShmemInitHash("LOCK hash",
428 : init_table_size,
429 : max_table_size,
430 : &info,
431 : HASH_ELEM | HASH_BLOBS | HASH_PARTITION);
432 :
433 : /* Assume an average of 2 holders per lock */
6328 434 1826 : max_table_size *= 2;
435 1826 : init_table_size *= 2;
436 :
437 : /*
438 : * Allocate hash table for PROCLOCK structs. This stores
439 : * per-lock-per-holder information.
440 : */
7569 bruce 441 1826 : info.keysize = sizeof(PROCLOCKTAG);
442 1826 : info.entrysize = sizeof(PROCLOCK);
6104 tgl 443 1826 : info.hash = proclock_hash;
444 1826 : info.num_partitions = NUM_LOCK_PARTITIONS;
445 :
446 1826 : LockMethodProcLockHash = ShmemInitHash("PROCLOCK hash",
447 : init_table_size,
448 : max_table_size,
449 : &info,
450 : HASH_ELEM | HASH_FUNCTION | HASH_PARTITION);
451 :
452 : /*
453 : * Allocate fast-path structures.
454 : */
4282 rhaas 455 1826 : FastPathStrongRelationLocks =
456 1826 : ShmemInitStruct("Fast Path Strong Relation Lock Data",
457 : sizeof(FastPathStrongRelationLockData), &found);
4334 458 1826 : if (!found)
4282 459 1826 : SpinLockInit(&FastPathStrongRelationLocks->mutex);
460 :
461 : /*
462 : * Allocate non-shared hash table for LOCALLOCK structs. This stores lock
463 : * counts and resource owner information.
464 : *
465 : * The non-shared table could already exist in this process (this occurs
466 : * when the postmaster is recreating shared memory after a backend crash).
467 : * If so, delete and recreate it. (We could simply leave it, since it
468 : * ought to be empty in the postmaster, but for safety let's zap it.)
469 : */
6330 tgl 470 1826 : if (LockMethodLocalHash)
471 4 : hash_destroy(LockMethodLocalHash);
472 :
6799 473 1826 : info.keysize = sizeof(LOCALLOCKTAG);
474 1826 : info.entrysize = sizeof(LOCALLOCK);
475 :
6330 476 1826 : LockMethodLocalHash = hash_create("LOCALLOCK hash",
477 : 16,
478 : &info,
479 : HASH_ELEM | HASH_BLOBS);
9770 scrappy 480 1826 : }
481 :
482 :
483 : /*
484 : * Fetch the lock method table associated with a given lock
485 : */
486 : LockMethod
6330 tgl 487 93 : GetLocksMethodTable(const LOCK *lock)
488 : {
489 93 : LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
490 :
491 93 : Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
492 93 : return LockMethods[lockmethodid];
493 : }
494 :
495 : /*
496 : * Fetch the lock method table associated with a given locktag
497 : */
498 : LockMethod
2603 499 1089 : GetLockTagsMethodTable(const LOCKTAG *locktag)
500 : {
501 1089 : LOCKMETHODID lockmethodid = (LOCKMETHODID) locktag->locktag_lockmethodid;
502 :
503 1089 : Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
504 1089 : return LockMethods[lockmethodid];
505 : }
506 :
507 :
508 : /*
509 : * Compute the hash code associated with a LOCKTAG.
510 : *
511 : * To avoid unnecessary recomputations of the hash code, we try to do this
512 : * just once per function, and then pass it around as needed. Aside from
513 : * passing the hashcode to hash_search_with_hash_value(), we can extract
514 : * the lock partition number from the hashcode.
515 : */
516 : uint32
6104 517 27079921 : LockTagHashCode(const LOCKTAG *locktag)
518 : {
519 27079921 : return get_hash_value(LockMethodLockHash, (const void *) locktag);
520 : }
521 :
522 : /*
523 : * Compute the hash code associated with a PROCLOCKTAG.
524 : *
525 : * Because we want to use just one set of partition locks for both the
526 : * LOCK and PROCLOCK hash tables, we have to make sure that PROCLOCKs
527 : * fall into the same partition number as their associated LOCKs.
528 : * dynahash.c expects the partition number to be the low-order bits of
529 : * the hash code, and therefore a PROCLOCKTAG's hash code must have the
530 : * same low-order bits as the associated LOCKTAG's hash code. We achieve
531 : * this with this specialized hash function.
532 : */
533 : static uint32
534 799 : proclock_hash(const void *key, Size keysize)
535 : {
536 799 : const PROCLOCKTAG *proclocktag = (const PROCLOCKTAG *) key;
537 : uint32 lockhash;
538 : Datum procptr;
539 :
540 799 : Assert(keysize == sizeof(PROCLOCKTAG));
541 :
542 : /* Look into the associated LOCK object, and compute its hash code */
543 799 : lockhash = LockTagHashCode(&proclocktag->myLock->tag);
544 :
545 : /*
546 : * To make the hash code also depend on the PGPROC, we xor the proc
547 : * struct's address into the hash code, left-shifted so that the
548 : * partition-number bits don't change. Since this is only a hash, we
549 : * don't care if we lose high-order bits of the address; use an
550 : * intermediate variable to suppress cast-pointer-to-int warnings.
551 : */
552 799 : procptr = PointerGetDatum(proclocktag->myProc);
553 799 : lockhash ^= ((uint32) procptr) << LOG2_NUM_LOCK_PARTITIONS;
554 :
555 799 : return lockhash;
556 : }
557 :
558 : /*
559 : * Compute the hash code associated with a PROCLOCKTAG, given the hashcode
560 : * for its underlying LOCK.
561 : *
562 : * We use this just to avoid redundant calls of LockTagHashCode().
563 : */
564 : static inline uint32
565 6745001 : ProcLockHashCode(const PROCLOCKTAG *proclocktag, uint32 hashcode)
566 : {
6031 bruce 567 6745001 : uint32 lockhash = hashcode;
568 : Datum procptr;
569 :
570 : /*
571 : * This must match proclock_hash()!
572 : */
6104 tgl 573 6745001 : procptr = PointerGetDatum(proclocktag->myProc);
574 6745001 : lockhash ^= ((uint32) procptr) << LOG2_NUM_LOCK_PARTITIONS;
575 :
576 6745001 : return lockhash;
577 : }
578 :
579 : /*
580 : * Given two lock modes, return whether they would conflict.
581 : */
582 : bool
3728 alvherre 583 132574 : DoLockModesConflict(LOCKMODE mode1, LOCKMODE mode2)
584 : {
585 132574 : LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
586 :
587 132574 : if (lockMethodTable->conflictTab[mode1] & LOCKBIT_ON(mode2))
588 132478 : return true;
589 :
590 96 : return false;
591 : }
592 :
593 : /*
594 : * LockHeldByMe -- test whether lock 'locktag' is held with mode 'lockmode'
595 : * by the current transaction
596 : */
597 : bool
1651 tgl 598 5429526 : LockHeldByMe(const LOCKTAG *locktag, LOCKMODE lockmode)
599 : {
600 : LOCALLOCKTAG localtag;
601 : LOCALLOCK *locallock;
602 :
603 : /*
604 : * See if there is a LOCALLOCK entry for this lock and lockmode
605 : */
606 5429526 : MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
607 5429526 : localtag.lock = *locktag;
608 5429526 : localtag.mode = lockmode;
609 :
610 5429526 : locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
611 : &localtag,
612 : HASH_FIND, NULL);
613 :
614 5429526 : return (locallock && locallock->nLocks > 0);
615 : }
616 :
617 : #ifdef USE_ASSERT_CHECKING
618 : /*
619 : * GetLockMethodLocalHash -- return the hash of local locks, for modules that
620 : * evaluate assertions based on all locks held.
621 : */
622 : HTAB *
1100 noah 623 5329 : GetLockMethodLocalHash(void)
624 : {
625 5329 : return LockMethodLocalHash;
626 : }
627 : #endif
628 :
629 : /*
630 : * LockHasWaiters -- look up 'locktag' and check if releasing this
631 : * lock would wake up other processes waiting for it.
632 : */
633 : bool
3771 kgrittn 634 UBC 0 : LockHasWaiters(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
635 : {
636 0 : LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
637 : LockMethod lockMethodTable;
638 : LOCALLOCKTAG localtag;
639 : LOCALLOCK *locallock;
640 : LOCK *lock;
641 : PROCLOCK *proclock;
642 : LWLock *partitionLock;
643 0 : bool hasWaiters = false;
644 :
645 0 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
646 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
647 0 : lockMethodTable = LockMethods[lockmethodid];
648 0 : if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
649 0 : elog(ERROR, "unrecognized lock mode: %d", lockmode);
650 :
651 : #ifdef LOCK_DEBUG
652 : if (LOCK_DEBUG_ENABLED(locktag))
653 : elog(LOG, "LockHasWaiters: lock [%u,%u] %s",
654 : locktag->locktag_field1, locktag->locktag_field2,
655 : lockMethodTable->lockModeNames[lockmode]);
656 : #endif
657 :
658 : /*
659 : * Find the LOCALLOCK entry for this lock and lockmode
660 : */
2118 tgl 661 0 : MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
3771 kgrittn 662 0 : localtag.lock = *locktag;
663 0 : localtag.mode = lockmode;
664 :
665 0 : locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
666 : &localtag,
667 : HASH_FIND, NULL);
668 :
669 : /*
670 : * let the caller print its own error message, too. Do not ereport(ERROR).
671 : */
672 0 : if (!locallock || locallock->nLocks <= 0)
673 : {
674 0 : elog(WARNING, "you don't own a lock of type %s",
675 : lockMethodTable->lockModeNames[lockmode]);
676 0 : return false;
677 : }
678 :
679 : /*
680 : * Check the shared lock table.
681 : */
682 0 : partitionLock = LockHashPartitionLock(locallock->hashcode);
683 :
684 0 : LWLockAcquire(partitionLock, LW_SHARED);
685 :
686 : /*
687 : * We don't need to re-find the lock or proclock, since we kept their
688 : * addresses in the locallock table, and they couldn't have been removed
689 : * while we were holding a lock on them.
690 : */
691 0 : lock = locallock->lock;
692 : LOCK_PRINT("LockHasWaiters: found", lock, lockmode);
693 0 : proclock = locallock->proclock;
694 : PROCLOCK_PRINT("LockHasWaiters: found", proclock);
695 :
696 : /*
697 : * Double-check that we are actually holding a lock of the type we want to
698 : * release.
699 : */
700 0 : if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
701 : {
702 : PROCLOCK_PRINT("LockHasWaiters: WRONGTYPE", proclock);
703 0 : LWLockRelease(partitionLock);
704 0 : elog(WARNING, "you don't own a lock of type %s",
705 : lockMethodTable->lockModeNames[lockmode]);
706 0 : RemoveLocalLock(locallock);
707 0 : return false;
708 : }
709 :
710 : /*
711 : * Do the checking.
712 : */
713 0 : if ((lockMethodTable->conflictTab[lockmode] & lock->waitMask) != 0)
714 0 : hasWaiters = true;
715 :
716 0 : LWLockRelease(partitionLock);
717 :
718 0 : return hasWaiters;
719 : }
720 :
721 : /*
722 : * LockAcquire -- Check for lock conflicts, sleep if conflict found,
723 : * set lock if/when no conflicts.
724 : *
725 : * Inputs:
726 : * locktag: unique identifier for the lockable object
727 : * lockmode: lock mode to acquire
728 : * sessionLock: if true, acquire lock for session not current transaction
729 : * dontWait: if true, don't wait to acquire lock
730 : *
731 : * Returns one of:
732 : * LOCKACQUIRE_NOT_AVAIL lock not available, and dontWait=true
733 : * LOCKACQUIRE_OK lock successfully acquired
734 : * LOCKACQUIRE_ALREADY_HELD incremented count for lock already held
735 : * LOCKACQUIRE_ALREADY_CLEAR incremented count for lock already clear
736 : *
737 : * In the normal case where dontWait=false and the caller doesn't need to
738 : * distinguish a freshly acquired lock from one already taken earlier in
739 : * this same transaction, there is no need to examine the return value.
740 : *
741 : * Side Effects: The lock is acquired and recorded in lock tables.
742 : *
743 : * NOTE: if we wait for the lock, there is no way to abort the wait
744 : * short of aborting the transaction.
745 : */
746 : LockAcquireResult
6330 tgl 747 CBC 945773 : LockAcquire(const LOCKTAG *locktag,
748 : LOCKMODE lockmode,
749 : bool sessionLock,
750 : bool dontWait)
751 : {
1675 752 945773 : return LockAcquireExtended(locktag, lockmode, sessionLock, dontWait,
753 : true, NULL);
754 : }
755 :
756 : /*
757 : * LockAcquireExtended - allows us to specify additional options
758 : *
759 : * reportMemoryError specifies whether a lock request that fills the lock
760 : * table should generate an ERROR or not. Passing "false" allows the caller
761 : * to attempt to recover from lock-table-full situations, perhaps by forcibly
762 : * canceling other lock holders and then retrying. Note, however, that the
763 : * return code for that is LOCKACQUIRE_NOT_AVAIL, so that it's unsafe to use
764 : * in combination with dontWait = true, as the cause of failure couldn't be
765 : * distinguished.
766 : *
767 : * If locallockp isn't NULL, *locallockp receives a pointer to the LOCALLOCK
768 : * table entry if a lock is successfully acquired, or NULL if not.
769 : */
770 : LockAcquireResult
4859 simon 771 28610314 : LockAcquireExtended(const LOCKTAG *locktag,
772 : LOCKMODE lockmode,
773 : bool sessionLock,
774 : bool dontWait,
775 : bool reportMemoryError,
776 : LOCALLOCK **locallockp)
777 : {
6330 tgl 778 28610314 : LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
779 : LockMethod lockMethodTable;
780 : LOCALLOCKTAG localtag;
781 : LOCALLOCK *locallock;
782 : LOCK *lock;
783 : PROCLOCK *proclock;
784 : bool found;
785 : ResourceOwner owner;
786 : uint32 hashcode;
787 : LWLock *partitionLock;
788 : bool found_conflict;
4514 simon 789 28610314 : bool log_lock = false;
790 :
6330 tgl 791 28610314 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
6330 tgl 792 UBC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
6330 tgl 793 CBC 28610314 : lockMethodTable = LockMethods[lockmethodid];
794 28610314 : if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
6330 tgl 795 UBC 0 : elog(ERROR, "unrecognized lock mode: %d", lockmode);
796 :
4859 simon 797 CBC 28610314 : if (RecoveryInProgress() && !InRecovery &&
798 173708 : (locktag->locktag_type == LOCKTAG_OBJECT ||
4790 bruce 799 173708 : locktag->locktag_type == LOCKTAG_RELATION) &&
800 : lockmode > RowExclusiveLock)
4859 simon 801 UBC 0 : ereport(ERROR,
802 : (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
803 : errmsg("cannot acquire lock mode %s on database objects while recovery is in progress",
804 : lockMethodTable->lockModeNames[lockmode]),
805 : errhint("Only RowExclusiveLock or less can be acquired on database objects during recovery.")));
806 :
807 : #ifdef LOCK_DEBUG
808 : if (LOCK_DEBUG_ENABLED(locktag))
809 : elog(LOG, "LockAcquire: lock [%u,%u] %s",
810 : locktag->locktag_field1, locktag->locktag_field2,
811 : lockMethodTable->lockModeNames[lockmode]);
812 : #endif
813 :
814 : /* Identify owner for lock */
3992 tgl 815 CBC 28610314 : if (sessionLock)
6799 816 58222 : owner = NULL;
817 : else
3992 818 28552092 : owner = CurrentResourceOwner;
819 :
820 : /*
821 : * Find or create a LOCALLOCK entry for this lock and lockmode
822 : */
2118 823 28610314 : MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
6799 824 28610314 : localtag.lock = *locktag;
825 28610314 : localtag.mode = lockmode;
826 :
6330 827 28610314 : locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
828 : &localtag,
829 : HASH_ENTER, &found);
830 :
831 : /*
832 : * if it's a new locallock object, initialize it
833 : */
6799 834 28610314 : if (!found)
835 : {
836 26137790 : locallock->lock = NULL;
837 26137790 : locallock->proclock = NULL;
6104 838 26137790 : locallock->hashcode = LockTagHashCode(&(localtag.lock));
6799 839 26137790 : locallock->nLocks = 0;
1675 840 26137790 : locallock->holdsStrongLockCount = false;
841 26137790 : locallock->lockCleared = false;
6799 842 26137790 : locallock->numLockOwners = 0;
843 26137790 : locallock->maxLockOwners = 8;
2758 844 26137790 : locallock->lockOwners = NULL; /* in case next line fails */
6799 845 26137790 : locallock->lockOwners = (LOCALLOCKOWNER *)
846 26137790 : MemoryContextAlloc(TopMemoryContext,
2118 847 26137790 : locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
848 : }
849 : else
850 : {
851 : /* Make sure there will be room to remember the lock */
6799 852 2472524 : if (locallock->numLockOwners >= locallock->maxLockOwners)
853 : {
6797 bruce 854 19 : int newsize = locallock->maxLockOwners * 2;
855 :
6799 tgl 856 19 : locallock->lockOwners = (LOCALLOCKOWNER *)
857 19 : repalloc(locallock->lockOwners,
858 : newsize * sizeof(LOCALLOCKOWNER));
859 19 : locallock->maxLockOwners = newsize;
860 : }
861 : }
4334 rhaas 862 28610314 : hashcode = locallock->hashcode;
863 :
1675 tgl 864 28610314 : if (locallockp)
865 27664541 : *locallockp = locallock;
866 :
867 : /*
868 : * If we already hold the lock, we can just increase the count locally.
869 : *
870 : * If lockCleared is already set, caller need not worry about absorbing
871 : * sinval messages related to the lock's object.
872 : */
6799 873 28610314 : if (locallock->nLocks > 0)
874 : {
875 2472524 : GrantLockLocal(locallock, owner);
1675 876 2472524 : if (locallock->lockCleared)
877 2371290 : return LOCKACQUIRE_ALREADY_CLEAR;
878 : else
879 101234 : return LOCKACQUIRE_ALREADY_HELD;
880 : }
881 :
882 : /*
883 : * We don't acquire any other heavyweight lock while holding the relation
884 : * extension lock. We do allow to acquire the same relation extension
885 : * lock more than once but that case won't reach here.
886 : */
1117 akapila 887 26137790 : Assert(!IsRelationExtensionLockHeld);
888 :
889 : /*
890 : * We don't acquire any other heavyweight lock while holding the page lock
891 : * except for relation extension.
892 : */
1116 893 26137790 : Assert(!IsPageLockHeld ||
894 : (locktag->locktag_type == LOCKTAG_RELATION_EXTEND));
895 :
896 : /*
897 : * Prepare to emit a WAL record if acquisition of this lock needs to be
898 : * replayed in a standby server.
899 : *
900 : * Here we prepare to log; after lock is acquired we'll issue log record.
901 : * This arrangement simplifies error recovery in case the preparation step
902 : * fails.
903 : *
904 : * Only AccessExclusiveLocks can conflict with lock types that read-only
905 : * transactions can acquire in a standby server. Make sure this definition
906 : * matches the one in GetRunningTransactionLocks().
907 : */
4514 simon 908 26137790 : if (lockmode >= AccessExclusiveLock &&
909 299428 : locktag->locktag_type == LOCKTAG_RELATION &&
910 240460 : !RecoveryInProgress() &&
911 221317 : XLogStandbyInfoActive())
912 : {
913 197730 : LogAccessExclusiveLockPrepare();
914 197730 : log_lock = true;
915 : }
916 :
917 : /*
918 : * Attempt to take lock via fast path, if eligible. But if we remember
919 : * having filled up the fast path array, we don't attempt to make any
920 : * further use of it until we release some locks. It's possible that some
921 : * other backend has transferred some of those locks to the shared hash
922 : * table, leaving space free, but it's not worth acquiring the LWLock just
923 : * to check. It's also possible that we're acquiring a second or third
924 : * lock type on a relation we have already locked using the fast-path, but
925 : * for now we don't worry about that case either.
926 : */
3420 tgl 927 26137790 : if (EligibleForRelationFastPath(locktag, lockmode) &&
928 23674570 : FastPathLocalUseCount < FP_LOCK_SLOTS_PER_BACKEND)
929 : {
3955 bruce 930 23455377 : uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
931 : bool acquired;
932 :
933 : /*
934 : * LWLockAcquire acts as a memory sequencing point, so it's safe to
935 : * assume that any strong locker whose increment to
936 : * FastPathStrongRelationLocks->counts becomes visible after we test
937 : * it has yet to begin to transfer fast-path locks.
938 : */
1059 tgl 939 23455377 : LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE);
3966 rhaas 940 23455377 : if (FastPathStrongRelationLocks->count[fasthashcode] != 0)
941 1358459 : acquired = false;
942 : else
943 22096918 : acquired = FastPathGrantRelationLock(locktag->locktag_field2,
944 : lockmode);
1059 tgl 945 23455377 : LWLockRelease(&MyProc->fpInfoLock);
3966 rhaas 946 23455377 : if (acquired)
947 : {
948 : /*
949 : * The locallock might contain stale pointers to some old shared
950 : * objects; we MUST reset these to null before considering the
951 : * lock to be acquired via fast-path.
952 : */
3420 tgl 953 22096918 : locallock->lock = NULL;
954 22096918 : locallock->proclock = NULL;
3966 rhaas 955 22096918 : GrantLockLocal(locallock, owner);
956 22096918 : return LOCKACQUIRE_OK;
957 : }
958 : }
959 :
960 : /*
961 : * If this lock could potentially have been taken via the fast-path by
962 : * some other backend, we must (temporarily) disable further use of the
963 : * fast-path for this lock tag, and migrate any locks already taken via
964 : * this method to the main lock table.
965 : */
966 4040872 : if (ConflictsWithRelationFastPath(locktag, lockmode))
967 : {
3955 bruce 968 271615 : uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
969 :
3966 rhaas 970 271615 : BeginStrongLockAcquire(locallock, fasthashcode);
971 271615 : if (!FastPathTransferRelationLocks(lockMethodTable, locktag,
972 : hashcode))
973 : {
3966 rhaas 974 UBC 0 : AbortStrongLockAcquire();
1675 tgl 975 0 : if (locallock->nLocks == 0)
976 0 : RemoveLocalLock(locallock);
977 0 : if (locallockp)
978 0 : *locallockp = NULL;
3966 rhaas 979 0 : if (reportMemoryError)
980 0 : ereport(ERROR,
981 : (errcode(ERRCODE_OUT_OF_MEMORY),
982 : errmsg("out of shared memory"),
983 : errhint("You might need to increase max_locks_per_transaction.")));
984 : else
985 0 : return LOCKACQUIRE_NOT_AVAIL;
986 : }
987 : }
988 :
989 : /*
990 : * We didn't find the lock in our LOCALLOCK table, and we didn't manage to
991 : * take it via the fast-path, either, so we've got to mess with the shared
992 : * lock table.
993 : */
6104 tgl 994 CBC 4040872 : partitionLock = LockHashPartitionLock(hashcode);
995 :
6328 996 4040872 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
997 :
998 : /*
999 : * Find or create lock and proclock entries with this tag
1000 : *
1001 : * Note: if the locallock object already existed, it might have a pointer
1002 : * to the lock already ... but we should not assume that that pointer is
1003 : * valid, since a lock object with zero hold and request counts can go
1004 : * away anytime. So we have to use SetupLockInTable() to recompute the
1005 : * lock and proclock pointers, even if they're already set.
1006 : */
4334 rhaas 1007 4040872 : proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
1008 : hashcode, lockmode);
1009 4040872 : if (!proclock)
1010 : {
4008 rhaas 1011 UBC 0 : AbortStrongLockAcquire();
4334 1012 0 : LWLockRelease(partitionLock);
1675 tgl 1013 0 : if (locallock->nLocks == 0)
1014 0 : RemoveLocalLock(locallock);
1015 0 : if (locallockp)
1016 0 : *locallockp = NULL;
4334 rhaas 1017 0 : if (reportMemoryError)
1018 0 : ereport(ERROR,
1019 : (errcode(ERRCODE_OUT_OF_MEMORY),
1020 : errmsg("out of shared memory"),
1021 : errhint("You might need to increase max_locks_per_transaction.")));
1022 : else
1023 0 : return LOCKACQUIRE_NOT_AVAIL;
1024 : }
4334 rhaas 1025 CBC 4040872 : locallock->proclock = proclock;
1026 4040872 : lock = proclock->tag.myLock;
1027 4040872 : locallock->lock = lock;
1028 :
1029 : /*
1030 : * If lock requested conflicts with locks requested by waiters, must join
1031 : * wait queue. Otherwise, check for conflict with already-held locks.
1032 : * (That's last because most complex check.)
1033 : */
1034 4040872 : if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
1197 peter 1035 26 : found_conflict = true;
1036 : else
1037 4040846 : found_conflict = LockCheckConflicts(lockMethodTable, lockmode,
1038 : lock, proclock);
1039 :
1040 4040872 : if (!found_conflict)
1041 : {
1042 : /* No conflict with held or previously requested locks */
4334 rhaas 1043 4039195 : GrantLock(lock, proclock, lockmode);
1044 4039195 : GrantLockLocal(locallock, owner);
1045 : }
1046 : else
1047 : {
1048 : /*
1049 : * We can't acquire the lock immediately. If caller specified no
1050 : * blocking, remove useless table entries and return
1051 : * LOCKACQUIRE_NOT_AVAIL without waiting.
1052 : */
1053 1677 : if (dontWait)
1054 : {
4008 1055 647 : AbortStrongLockAcquire();
4334 1056 647 : if (proclock->holdMask == 0)
1057 : {
1058 : uint32 proclock_hashcode;
1059 :
1060 445 : proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
81 andres 1061 GNC 445 : dlist_delete(&proclock->lockLink);
1062 445 : dlist_delete(&proclock->procLink);
4334 rhaas 1063 CBC 445 : if (!hash_search_with_hash_value(LockMethodProcLockHash,
62 peter 1064 GNC 445 : &(proclock->tag),
1065 : proclock_hashcode,
1066 : HASH_REMOVE,
1067 : NULL))
4334 rhaas 1068 UBC 0 : elog(PANIC, "proclock table corrupted");
1069 : }
1070 : else
1071 : PROCLOCK_PRINT("LockAcquire: NOWAIT", proclock);
4334 rhaas 1072 CBC 647 : lock->nRequested--;
1073 647 : lock->requested[lockmode]--;
1074 : LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
1075 647 : Assert((lock->nRequested > 0) && (lock->requested[lockmode] >= 0));
1076 647 : Assert(lock->nGranted <= lock->nRequested);
1077 647 : LWLockRelease(partitionLock);
1078 647 : if (locallock->nLocks == 0)
1079 647 : RemoveLocalLock(locallock);
1675 tgl 1080 647 : if (locallockp)
1081 220 : *locallockp = NULL;
4334 rhaas 1082 647 : return LOCKACQUIRE_NOT_AVAIL;
1083 : }
1084 :
1085 : /*
1086 : * Set bitmask of locks this process already holds on this object.
1087 : */
1088 1030 : MyProc->heldLocks = proclock->holdMask;
1089 :
1090 : /*
1091 : * Sleep till someone wakes me up.
1092 : */
1093 :
1094 : TRACE_POSTGRESQL_LOCK_WAIT_START(locktag->locktag_field1,
1095 : locktag->locktag_field2,
1096 : locktag->locktag_field3,
1097 : locktag->locktag_field4,
1098 : locktag->locktag_type,
1099 : lockmode);
1100 :
1101 1030 : WaitOnLock(locallock, owner);
1102 :
1103 : TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
1104 : locktag->locktag_field2,
1105 : locktag->locktag_field3,
1106 : locktag->locktag_field4,
1107 : locktag->locktag_type,
1108 : lockmode);
1109 :
1110 : /*
1111 : * NOTE: do not do any material change of state between here and
1112 : * return. All required changes in locktable state must have been
1113 : * done when the lock was granted to us --- see notes in WaitOnLock.
1114 : */
1115 :
1116 : /*
1117 : * Check the proclock entry status, in case something in the ipc
1118 : * communication doesn't work correctly.
1119 : */
1120 983 : if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
1121 : {
4008 rhaas 1122 UBC 0 : AbortStrongLockAcquire();
1123 : PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
1124 : LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
1125 : /* Should we retry ? */
4334 1126 0 : LWLockRelease(partitionLock);
1127 0 : elog(ERROR, "LockAcquire failed");
1128 : }
1129 : PROCLOCK_PRINT("LockAcquire: granted", proclock);
1130 : LOCK_PRINT("LockAcquire: granted", lock, lockmode);
1131 : }
1132 :
1133 : /*
1134 : * Lock state is fully up-to-date now; if we error out after this, no
1135 : * special error cleanup is required.
1136 : */
4008 rhaas 1137 CBC 4040178 : FinishStrongLockAcquire();
1138 :
4334 1139 4040178 : LWLockRelease(partitionLock);
1140 :
1141 : /*
1142 : * Emit a WAL record if acquisition of this lock needs to be replayed in a
1143 : * standby server.
1144 : */
1145 4040178 : if (log_lock)
1146 : {
1147 : /*
1148 : * Decode the locktag back to the original values, to avoid sending
1149 : * lots of empty bytes with every message. See lock.h to check how a
1150 : * locktag is defined for LOCKTAG_RELATION
1151 : */
1152 197518 : LogAccessExclusiveLock(locktag->locktag_field1,
1153 197518 : locktag->locktag_field2);
1154 : }
1155 :
1156 4040178 : return LOCKACQUIRE_OK;
1157 : }
1158 :
1159 : /*
1160 : * Find or create LOCK and PROCLOCK objects as needed for a new lock
1161 : * request.
1162 : *
1163 : * Returns the PROCLOCK object, or NULL if we failed to create the objects
1164 : * for lack of shared memory.
1165 : *
1166 : * The appropriate partition lock must be held at entry, and will be
1167 : * held at exit.
1168 : */
1169 : static PROCLOCK *
1170 4042461 : SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
1171 : const LOCKTAG *locktag, uint32 hashcode, LOCKMODE lockmode)
1172 : {
1173 : LOCK *lock;
1174 : PROCLOCK *proclock;
1175 : PROCLOCKTAG proclocktag;
1176 : uint32 proclock_hashcode;
1177 : bool found;
1178 :
1179 : /*
1180 : * Find or create a lock with this tag.
1181 : */
6104 tgl 1182 4042461 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
1183 : locktag,
1184 : hashcode,
1185 : HASH_ENTER_NULL,
1186 : &found);
9345 bruce 1187 4042461 : if (!lock)
4334 rhaas 1188 UBC 0 : return NULL;
1189 :
1190 : /*
1191 : * if it's a new lock object, initialize it
1192 : */
9345 bruce 1193 CBC 4042461 : if (!found)
1194 : {
8118 tgl 1195 2677474 : lock->grantMask = 0;
1196 2677474 : lock->waitMask = 0;
81 andres 1197 GNC 2677474 : dlist_init(&lock->procLocks);
1198 2677474 : dclist_init(&lock->waitProcs);
8118 tgl 1199 CBC 2677474 : lock->nRequested = 0;
1200 2677474 : lock->nGranted = 0;
6542 neilc 1201 16064844 : MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
1202 2677474 : MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
1203 : LOCK_PRINT("LockAcquire: new", lock, lockmode);
1204 : }
1205 : else
1206 : {
1207 : LOCK_PRINT("LockAcquire: found", lock, lockmode);
8118 tgl 1208 1364987 : Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
1209 1364987 : Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
1210 1364987 : Assert(lock->nGranted <= lock->nRequested);
1211 : }
1212 :
1213 : /*
1214 : * Create the hash key for the proclock table.
1215 : */
6104 1216 4042461 : proclocktag.myLock = lock;
4334 rhaas 1217 4042461 : proclocktag.myProc = proc;
1218 :
6104 tgl 1219 4042461 : proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
1220 :
1221 : /*
1222 : * Find or create a proclock entry with this tag
1223 : */
1224 4042461 : proclock = (PROCLOCK *) hash_search_with_hash_value(LockMethodProcLockHash,
1225 : &proclocktag,
1226 : proclock_hashcode,
1227 : HASH_ENTER_NULL,
1228 : &found);
7355 bruce 1229 4042461 : if (!proclock)
1230 : {
1231 : /* Oops, not enough shmem for the proclock */
6783 tgl 1232 UBC 0 : if (lock->nRequested == 0)
1233 : {
1234 : /*
1235 : * There are no other requestors of this lock, so garbage-collect
1236 : * the lock object. We *must* do this to avoid a permanent leak
1237 : * of shared memory, because there won't be anything to cause
1238 : * anyone to release the lock object later.
1239 : */
81 andres 1240 UNC 0 : Assert(dlist_is_empty(&(lock->procLocks)));
6104 tgl 1241 UBC 0 : if (!hash_search_with_hash_value(LockMethodLockHash,
62 peter 1242 UNC 0 : &(lock->tag),
1243 : hashcode,
1244 : HASH_REMOVE,
1245 : NULL))
6534 tgl 1246 UBC 0 : elog(PANIC, "lock table corrupted");
1247 : }
4334 rhaas 1248 0 : return NULL;
1249 : }
1250 :
1251 : /*
1252 : * If new, initialize the new entry
1253 : */
9345 bruce 1254 CBC 4042461 : if (!found)
1255 : {
4334 rhaas 1256 2700380 : uint32 partition = LockHashPartition(hashcode);
1257 :
1258 : /*
1259 : * It might seem unsafe to access proclock->groupLeader without a
1260 : * lock, but it's not really. Either we are initializing a proclock
1261 : * on our own behalf, in which case our group leader isn't changing
1262 : * because the group leader for a process can only ever be changed by
1263 : * the process itself; or else we are transferring a fast-path lock to
1264 : * the main lock table, in which case that process can't change it's
1265 : * lock group leader without first releasing all of its locks (and in
1266 : * particular the one we are currently transferring).
1267 : */
2618 1268 5400760 : proclock->groupLeader = proc->lockGroupLeader != NULL ?
1269 2700380 : proc->lockGroupLeader : proc;
6799 tgl 1270 2700380 : proclock->holdMask = 0;
6508 1271 2700380 : proclock->releaseMask = 0;
1272 : /* Add proclock to appropriate lists */
81 andres 1273 GNC 2700380 : dlist_push_tail(&lock->procLocks, &proclock->lockLink);
1274 2700380 : dlist_push_tail(&proc->myProcLocks[partition], &proclock->procLink);
1275 : PROCLOCK_PRINT("LockAcquire: new", proclock);
1276 : }
1277 : else
1278 : {
7355 bruce 1279 ECB : PROCLOCK_PRINT("LockAcquire: found", proclock);
6799 tgl 1280 GIC 1342081 : Assert((proclock->holdMask & ~lock->grantMask) == 0);
1281 :
1282 : #ifdef CHECK_DEADLOCK_RISK
1283 :
1284 : /*
1285 : * Issue warning if we already hold a lower-level lock on this object
1286 : * and do not hold a lock of the requested level or higher. This
1287 : * indicates a deadlock-prone coding practice (eg, we'd have a
1288 : * deadlock if another backend were following the same code path at
1289 : * about the same time).
1290 : *
1291 : * This is not enabled by default, because it may generate log entries
1292 : * about user-level coding practices that are in fact safe in context.
1293 : * It can be enabled to help find system-level problems.
1294 : *
1295 : * XXX Doing numeric comparison on the lockmodes is a hack; it'd be
1296 : * better to use a table. For now, though, this works.
1297 : */
1298 : {
1299 : int i;
1300 :
1301 : for (i = lockMethodTable->numLockModes; i > 0; i--)
1302 : {
1303 : if (proclock->holdMask & LOCKBIT_ON(i))
1304 : {
1305 : if (i >= (int) lockmode)
1306 : break; /* safe: we have a lock >= req level */
1307 : elog(LOG, "deadlock risk: raising lock level"
1308 : " from %s to %s on object %u/%u/%u",
1309 : lockMethodTable->lockModeNames[i],
1310 : lockMethodTable->lockModeNames[lockmode],
1311 : lock->tag.locktag_field1, lock->tag.locktag_field2,
1312 : lock->tag.locktag_field3);
1313 : break;
1314 : }
1315 : }
1316 : }
1317 : #endif /* CHECK_DEADLOCK_RISK */
1318 : }
1319 :
1320 : /*
1321 : * lock->nRequested and lock->requested[] count the total number of
1322 : * requests, whether granted or waiting, so increment those immediately.
1323 : * The other counts don't increment till we get the lock.
9345 bruce 1324 ECB : */
8118 tgl 1325 CBC 4042461 : lock->nRequested++;
1326 4042461 : lock->requested[lockmode]++;
8118 tgl 1327 GIC 4042461 : Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
1328 :
1329 : /*
1330 : * We shouldn't already hold the desired lock; else locallock table is
1331 : * broken.
9345 bruce 1332 ECB : */
6508 tgl 1333 GBC 4042461 : if (proclock->holdMask & LOCKBIT_ON(lockmode))
6508 tgl 1334 UIC 0 : elog(ERROR, "lock %s on object %u/%u/%u is already held",
1335 : lockMethodTable->lockModeNames[lockmode],
1336 : lock->tag.locktag_field1, lock->tag.locktag_field2,
1337 : lock->tag.locktag_field3);
9345 bruce 1338 ECB :
4334 rhaas 1339 GIC 4042461 : return proclock;
1340 : }
1341 :
1342 : /*
1343 : * Check and set/reset the flag that we hold the relation extension/page lock.
1344 : *
1345 : * It is callers responsibility that this function is called after
1346 : * acquiring/releasing the relation extension/page lock.
1347 : *
1348 : * Pass acquired as true if lock is acquired, false otherwise.
1349 : */
1117 akapila 1350 ECB : static inline void
1117 akapila 1351 GIC 52620064 : CheckAndSetLockHeld(LOCALLOCK *locallock, bool acquired)
1352 : {
1117 akapila 1353 ECB : #ifdef USE_ASSERT_CHECKING
1117 akapila 1354 CBC 52620064 : if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_RELATION_EXTEND)
1355 651318 : IsRelationExtensionLockHeld = acquired;
1116 1356 51968746 : else if (LOCALLOCK_LOCKTAG(*locallock) == LOCKTAG_PAGE)
1116 akapila 1357 GIC 80 : IsPageLockHeld = acquired;
1358 :
1117 akapila 1359 ECB : #endif
1117 akapila 1360 GIC 52620064 : }
1361 :
1362 : /*
1363 : * Subroutine to free a locallock entry
1364 : */
6799 tgl 1365 ECB : static void
6799 tgl 1366 GIC 26137790 : RemoveLocalLock(LOCALLOCK *locallock)
1367 : {
1368 : int i;
3944 heikki.linnakangas 1369 ECB :
3944 heikki.linnakangas 1370 GIC 26196832 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
3944 heikki.linnakangas 1371 ECB : {
3944 heikki.linnakangas 1372 CBC 59042 : if (locallock->lockOwners[i].owner != NULL)
3944 heikki.linnakangas 1373 GIC 59008 : ResourceOwnerForgetLock(locallock->lockOwners[i].owner, locallock);
3944 heikki.linnakangas 1374 ECB : }
2758 tgl 1375 CBC 26137790 : locallock->numLockOwners = 0;
1376 26137790 : if (locallock->lockOwners != NULL)
1377 26137790 : pfree(locallock->lockOwners);
6799 tgl 1378 GIC 26137790 : locallock->lockOwners = NULL;
3944 heikki.linnakangas 1379 ECB :
4334 rhaas 1380 GIC 26137790 : if (locallock->holdsStrongLockCount)
1381 : {
1382 : uint32 fasthashcode;
3955 bruce 1383 ECB :
4334 rhaas 1384 GIC 271338 : fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
4334 rhaas 1385 ECB :
4282 rhaas 1386 CBC 271338 : SpinLockAcquire(&FastPathStrongRelationLocks->mutex);
1387 271338 : Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
1388 271338 : FastPathStrongRelationLocks->count[fasthashcode]--;
2062 peter_e 1389 271338 : locallock->holdsStrongLockCount = false;
4282 rhaas 1390 GIC 271338 : SpinLockRelease(&FastPathStrongRelationLocks->mutex);
1391 : }
3944 heikki.linnakangas 1392 ECB :
6330 tgl 1393 CBC 26137790 : if (!hash_search(LockMethodLocalHash,
62 peter 1394 GNC 26137790 : &(locallock->tag),
6534 tgl 1395 EUB : HASH_REMOVE, NULL))
6799 tgl 1396 UIC 0 : elog(WARNING, "locallock table corrupted");
1397 :
1398 : /*
1399 : * Indicate that the lock is released for certain types of locks
1117 akapila 1400 ECB : */
1117 akapila 1401 CBC 26137790 : CheckAndSetLockHeld(locallock, false);
6799 tgl 1402 GIC 26137790 : }
1403 :
1404 : /*
1405 : * LockCheckConflicts -- test whether requested lock conflicts
1406 : * with those already granted
1407 : *
1408 : * Returns true if conflict, false if no conflict.
1409 : *
1410 : * NOTES:
1411 : * Here's what makes this complicated: one process's locks don't
1412 : * conflict with one another, no matter what purpose they are held for
1413 : * (eg, session and transaction locks do not conflict). Nor do the locks
1414 : * of one process in a lock group conflict with those of another process in
1415 : * the same group. So, we must subtract off these locks when determining
1416 : * whether the requested new lock conflicts with those already held.
1417 : */
1197 peter 1418 ECB : bool
7069 bruce 1419 GIC 4041873 : LockCheckConflicts(LockMethod lockMethodTable,
1420 : LOCKMODE lockmode,
1421 : LOCK *lock,
1422 : PROCLOCK *proclock)
9770 scrappy 1423 ECB : {
7570 bruce 1424 GIC 4041873 : int numLockModes = lockMethodTable->numLockModes;
6508 tgl 1425 ECB : LOCKMASK myLocks;
2618 rhaas 1426 GIC 4041873 : int conflictMask = lockMethodTable->conflictTab[lockmode];
2618 rhaas 1427 ECB : int conflictsRemaining[MAX_LOCKMODES];
2618 rhaas 1428 GIC 4041873 : int totalConflictsRemaining = 0;
1429 : dlist_iter proclock_iter;
1430 : int i;
1431 :
1432 : /*
1433 : * first check for global conflicts: If no locks conflict with my request,
1434 : * then I get the lock.
1435 : *
1436 : * Checking for conflict: lock->grantMask represents the types of
1437 : * currently held locks. conflictTable[lockmode] has a bit set for each
1438 : * type of lock that conflicts with request. Bitwise compare tells if
6347 bruce 1439 ECB : * there is a conflict.
1440 : */
2618 rhaas 1441 GIC 4041873 : if (!(conflictMask & lock->grantMask))
9770 scrappy 1442 ECB : {
1443 : PROCLOCK_PRINT("LockCheckConflicts: no conflict", proclock);
1197 peter 1444 GIC 3783227 : return false;
1445 : }
1446 :
1447 : /*
1448 : * Rats. Something conflicts. But it could still be my own lock, or a
1449 : * lock held by another member of my locking group. First, figure out how
2495 rhaas 1450 ECB : * many conflicts remain after subtracting out any locks I hold myself.
9345 bruce 1451 : */
6508 tgl 1452 GIC 258646 : myLocks = proclock->holdMask;
7069 bruce 1453 CBC 2327814 : for (i = 1; i <= numLockModes; i++)
1454 : {
2618 rhaas 1455 2069168 : if ((conflictMask & LOCKBIT_ON(i)) == 0)
2618 rhaas 1456 ECB : {
2618 rhaas 1457 GIC 1069300 : conflictsRemaining[i] = 0;
2618 rhaas 1458 CBC 1069300 : continue;
2618 rhaas 1459 ECB : }
2618 rhaas 1460 CBC 999868 : conflictsRemaining[i] = lock->granted[i];
1461 999868 : if (myLocks & LOCKBIT_ON(i))
2618 rhaas 1462 GIC 260541 : --conflictsRemaining[i];
1463 999868 : totalConflictsRemaining += conflictsRemaining[i];
1464 : }
6508 tgl 1465 ECB :
1466 : /* If no conflicts remain, we get the lock. */
2618 rhaas 1467 GIC 258646 : if (totalConflictsRemaining == 0)
2618 rhaas 1468 ECB : {
1469 : PROCLOCK_PRINT("LockCheckConflicts: resolved (simple)", proclock);
1197 peter 1470 GIC 256523 : return false;
1471 : }
2618 rhaas 1472 ECB :
1473 : /* If no group locking, it's definitely a conflict. */
2618 rhaas 1474 CBC 2123 : if (proclock->groupLeader == MyProc && MyProc->lockGroupLeader == NULL)
1475 : {
2618 rhaas 1476 GIC 1649 : Assert(proclock->tag.myProc == MyProc);
2618 rhaas 1477 ECB : PROCLOCK_PRINT("LockCheckConflicts: conflicting (simple)",
1478 : proclock);
1197 peter 1479 GIC 1649 : return true;
1480 : }
1481 :
1482 : /*
1483 : * The relation extension or page lock conflict even between the group
1114 akapila 1484 ECB : * members.
1115 1485 : */
1114 akapila 1486 GIC 474 : if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND ||
1487 466 : (LOCK_LOCKTAG(*lock) == LOCKTAG_PAGE))
1488 : {
1115 akapila 1489 ECB : PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)",
1490 : proclock);
1115 akapila 1491 GIC 8 : return true;
1492 : }
1493 :
1494 : /*
1495 : * Locks held in conflicting modes by members of our own lock group are
1496 : * not real conflicts; we can subtract those out and see if we still have
1497 : * a conflict. This is O(N) in the number of processes holding or
1498 : * awaiting locks on this object. We could improve that by making the
1499 : * shared memory state more complex (and larger) but it doesn't seem worth
2495 rhaas 1500 ECB : * it.
1501 : */
81 andres 1502 GNC 631 : dlist_foreach(proclock_iter, &lock->procLocks)
9770 scrappy 1503 ECB : {
81 andres 1504 GNC 597 : PROCLOCK *otherproclock =
1505 597 : dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
1506 :
2618 rhaas 1507 CBC 597 : if (proclock != otherproclock &&
2618 rhaas 1508 GIC 563 : proclock->groupLeader == otherproclock->groupLeader &&
2618 rhaas 1509 CBC 435 : (otherproclock->holdMask & conflictMask) != 0)
1510 : {
2495 1511 433 : int intersectMask = otherproclock->holdMask & conflictMask;
1512 :
2618 1513 3897 : for (i = 1; i <= numLockModes; i++)
1514 : {
1515 3464 : if ((intersectMask & LOCKBIT_ON(i)) != 0)
2618 rhaas 1516 EUB : {
2618 rhaas 1517 CBC 440 : if (conflictsRemaining[i] <= 0)
2618 rhaas 1518 LBC 0 : elog(PANIC, "proclocks held do not match lock");
2618 rhaas 1519 GIC 440 : conflictsRemaining[i]--;
1520 440 : totalConflictsRemaining--;
1521 : }
2618 rhaas 1522 ECB : }
1523 :
2618 rhaas 1524 GIC 433 : if (totalConflictsRemaining == 0)
1525 : {
2618 rhaas 1526 ECB : PROCLOCK_PRINT("LockCheckConflicts: resolved (group)",
1527 : proclock);
1197 peter 1528 GIC 432 : return false;
1529 : }
1530 : }
1531 : }
1532 :
1533 : /* Nope, it's a real conflict. */
1534 : PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)", proclock);
1535 34 : return true;
1536 : }
1537 :
1538 : /*
1539 : * GrantLock -- update the lock and proclock data structures to show
1540 : * the lock request has been granted.
1541 : *
1542 : * NOTE: if proc was blocked, it also needs to be removed from the wait list
1543 : * and have its waitLock/waitProcLock fields cleared. That's not done here.
1544 : *
6799 tgl 1545 ECB : * NOTE: the lock grant also has to be recorded in the associated LOCALLOCK
1546 : * table entry; but since we may be awaking some other process, we can't do
1547 : * that here; it's done by GrantLockLocal, instead.
8993 scrappy 1548 : */
1549 : void
7355 bruce 1550 CBC 4041850 : GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
8993 scrappy 1551 ECB : {
8118 tgl 1552 CBC 4041850 : lock->nGranted++;
8118 tgl 1553 GIC 4041850 : lock->granted[lockmode]++;
7069 bruce 1554 CBC 4041850 : lock->grantMask |= LOCKBIT_ON(lockmode);
8118 tgl 1555 4041850 : if (lock->granted[lockmode] == lock->requested[lockmode])
7069 bruce 1556 4041713 : lock->waitMask &= LOCKBIT_OFF(lockmode);
6799 tgl 1557 GIC 4041850 : proclock->holdMask |= LOCKBIT_ON(lockmode);
1558 : LOCK_PRINT("GrantLock", lock, lockmode);
8118 1559 4041850 : Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
1560 4041850 : Assert(lock->nGranted <= lock->nRequested);
6799 1561 4041850 : }
1562 :
1563 : /*
1564 : * UnGrantLock -- opposite of GrantLock.
1565 : *
1566 : * Updates the lock and proclock data structures to show that the lock
1567 : * is no longer held nor requested by the current holder.
6638 neilc 1568 ECB : *
1569 : * Returns true if there were any waiters waiting on the lock that
1570 : * should now be woken up with ProcLockWakeup.
1571 : */
1572 : static bool
6638 neilc 1573 CBC 4041779 : UnGrantLock(LOCK *lock, LOCKMODE lockmode,
6638 neilc 1574 ECB : PROCLOCK *proclock, LockMethod lockMethodTable)
1575 : {
6385 bruce 1576 GIC 4041779 : bool wakeupNeeded = false;
1577 :
6638 neilc 1578 4041779 : Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
1579 4041779 : Assert((lock->nGranted > 0) && (lock->granted[lockmode] > 0));
6638 neilc 1580 CBC 4041779 : Assert(lock->nGranted <= lock->nRequested);
6638 neilc 1581 ECB :
1582 : /*
1583 : * fix the general lock stats
1584 : */
6638 neilc 1585 CBC 4041779 : lock->nRequested--;
6638 neilc 1586 GIC 4041779 : lock->requested[lockmode]--;
1587 4041779 : lock->nGranted--;
6638 neilc 1588 CBC 4041779 : lock->granted[lockmode]--;
1589 :
6638 neilc 1590 GIC 4041779 : if (lock->granted[lockmode] == 0)
1591 : {
1592 : /* change the conflict mask. No more of this lock type. */
1593 4024055 : lock->grantMask &= LOCKBIT_OFF(lockmode);
1594 : }
1595 :
1596 : LOCK_PRINT("UnGrantLock: updated", lock, lockmode);
1597 :
1598 : /*
1599 : * We need only run ProcLockWakeup if the released lock conflicts with at
1600 : * least one of the lock types requested by waiter(s). Otherwise whatever
1601 : * conflict made them wait must still exist. NOTE: before MVCC, we could
6385 bruce 1602 ECB : * skip wakeup if lock->granted[lockmode] was still positive. But that's
1603 : * not true anymore, because the remaining granted locks might belong to
1604 : * some waiter, who could now be awakened because he doesn't conflict with
1605 : * his own locks.
1606 : */
6638 neilc 1607 GIC 4041779 : if (lockMethodTable->conflictTab[lockmode] & lock->waitMask)
6638 neilc 1608 CBC 951 : wakeupNeeded = true;
1609 :
1610 : /*
6638 neilc 1611 ECB : * Now fix the per-proclock state.
1612 : */
6638 neilc 1613 GIC 4041779 : proclock->holdMask &= LOCKBIT_OFF(lockmode);
1614 : PROCLOCK_PRINT("UnGrantLock: updated", proclock);
1615 :
1616 4041779 : return wakeupNeeded;
1617 : }
1618 :
1619 : /*
1620 : * CleanUpLock -- clean up after releasing a lock. We garbage-collect the
1621 : * proclock and lock objects if possible, and call ProcLockWakeup if there
1622 : * are remaining requests and the caller says it's OK. (Normally, this
1623 : * should be called after UnGrantLock, and wakeupNeeded is the result from
1624 : * UnGrantLock.)
6534 tgl 1625 ECB : *
1626 : * The appropriate partition lock must be held at entry, and will be
1627 : * held at exit.
1628 : */
1629 : static void
6328 tgl 1630 GIC 4012126 : CleanUpLock(LOCK *lock, PROCLOCK *proclock,
1631 : LockMethod lockMethodTable, uint32 hashcode,
1632 : bool wakeupNeeded)
6534 tgl 1633 ECB : {
1634 : /*
1635 : * If this was my last hold on this lock, delete my entry in the proclock
1636 : * table.
1637 : */
6534 tgl 1638 CBC 4012126 : if (proclock->holdMask == 0)
6534 tgl 1639 ECB : {
6104 1640 : uint32 proclock_hashcode;
1641 :
6534 1642 : PROCLOCK_PRINT("CleanUpLock: deleting", proclock);
81 andres 1643 GNC 2699945 : dlist_delete(&proclock->lockLink);
1644 2699945 : dlist_delete(&proclock->procLink);
6104 tgl 1645 GIC 2699945 : proclock_hashcode = ProcLockHashCode(&proclock->tag, hashcode);
6104 tgl 1646 GBC 2699945 : if (!hash_search_with_hash_value(LockMethodProcLockHash,
62 peter 1647 GNC 2699945 : &(proclock->tag),
1648 : proclock_hashcode,
6104 tgl 1649 ECB : HASH_REMOVE,
1650 : NULL))
6534 tgl 1651 UIC 0 : elog(PANIC, "proclock table corrupted");
1652 : }
1653 :
6534 tgl 1654 GIC 4012126 : if (lock->nRequested == 0)
1655 : {
6534 tgl 1656 ECB : /*
6385 bruce 1657 : * The caller just released the last lock, so garbage-collect the lock
1658 : * object.
1659 : */
1660 : LOCK_PRINT("CleanUpLock: deleting", lock, 0);
81 andres 1661 GNC 2677476 : Assert(dlist_is_empty(&lock->procLocks));
6104 tgl 1662 GBC 2677476 : if (!hash_search_with_hash_value(LockMethodLockHash,
62 peter 1663 GNC 2677476 : &(lock->tag),
6104 tgl 1664 ECB : hashcode,
1665 : HASH_REMOVE,
1666 : NULL))
6534 tgl 1667 LBC 0 : elog(PANIC, "lock table corrupted");
1668 : }
6534 tgl 1669 CBC 1334650 : else if (wakeupNeeded)
1670 : {
1671 : /* There are waiters on this lock, so wake them up. */
6328 tgl 1672 GIC 995 : ProcLockWakeup(lockMethodTable, lock);
1673 : }
6534 1674 4012126 : }
1675 :
1676 : /*
1677 : * GrantLockLocal -- update the locallock data structures to show
1678 : * the lock request has been granted.
6799 tgl 1679 ECB : *
1680 : * We expect that LockAcquire made sure there is room to add a new
1681 : * ResourceOwner entry.
1682 : */
1683 : static void
6799 tgl 1684 CBC 28609622 : GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
1685 : {
1686 28609622 : LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
1687 : int i;
6799 tgl 1688 ECB :
6799 tgl 1689 GIC 28609622 : Assert(locallock->numLockOwners < locallock->maxLockOwners);
6799 tgl 1690 ECB : /* Count the total */
6799 tgl 1691 GIC 28609622 : locallock->nLocks++;
6799 tgl 1692 ECB : /* Count the per-owner lock */
6799 tgl 1693 CBC 29100035 : for (i = 0; i < locallock->numLockOwners; i++)
1694 : {
6799 tgl 1695 GIC 2617761 : if (lockOwners[i].owner == owner)
6799 tgl 1696 ECB : {
6799 tgl 1697 CBC 2127348 : lockOwners[i].nLocks++;
1698 2127348 : return;
6799 tgl 1699 ECB : }
1700 : }
6799 tgl 1701 GIC 26482274 : lockOwners[i].owner = owner;
1702 26482274 : lockOwners[i].nLocks = 1;
6799 tgl 1703 CBC 26482274 : locallock->numLockOwners++;
3944 heikki.linnakangas 1704 GIC 26482274 : if (owner != NULL)
1705 26424487 : ResourceOwnerRememberLock(owner, locallock);
1706 :
1707 : /* Indicate that the lock is acquired for certain types of locks. */
1117 akapila 1708 26482274 : CheckAndSetLockHeld(locallock, true);
1709 : }
1710 :
4008 rhaas 1711 ECB : /*
1712 : * BeginStrongLockAcquire - inhibit use of fastpath for a given LOCALLOCK,
1713 : * and arrange for error cleanup if it fails
1714 : */
1715 : static void
4008 rhaas 1716 GIC 271615 : BeginStrongLockAcquire(LOCALLOCK *locallock, uint32 fasthashcode)
1717 : {
1718 271615 : Assert(StrongLockInProgress == NULL);
2062 peter_e 1719 271615 : Assert(locallock->holdsStrongLockCount == false);
1720 :
1721 : /*
1722 : * Adding to a memory location is not atomic, so we take a spinlock to
1723 : * ensure we don't collide with someone else trying to bump the count at
1724 : * the same time.
4008 rhaas 1725 ECB : *
1726 : * XXX: It might be worth considering using an atomic fetch-and-add
1727 : * instruction here, on architectures where that is supported.
1728 : */
1729 :
4008 rhaas 1730 CBC 271615 : SpinLockAcquire(&FastPathStrongRelationLocks->mutex);
4008 rhaas 1731 GIC 271615 : FastPathStrongRelationLocks->count[fasthashcode]++;
2062 peter_e 1732 271615 : locallock->holdsStrongLockCount = true;
4008 rhaas 1733 271615 : StrongLockInProgress = locallock;
1734 271615 : SpinLockRelease(&FastPathStrongRelationLocks->mutex);
1735 271615 : }
1736 :
4008 rhaas 1737 ECB : /*
1738 : * FinishStrongLockAcquire - cancel pending cleanup for a strong lock
1739 : * acquisition once it's no longer needed
1740 : */
1741 : static void
4008 rhaas 1742 GIC 4040178 : FinishStrongLockAcquire(void)
1743 : {
1744 4040178 : StrongLockInProgress = NULL;
1745 4040178 : }
1746 :
4008 rhaas 1747 ECB : /*
1748 : * AbortStrongLockAcquire - undo strong lock state changes performed by
1749 : * BeginStrongLockAcquire.
1750 : */
1751 : void
4008 rhaas 1752 CBC 511890 : AbortStrongLockAcquire(void)
4008 rhaas 1753 ECB : {
1754 : uint32 fasthashcode;
4008 rhaas 1755 CBC 511890 : LOCALLOCK *locallock = StrongLockInProgress;
3955 bruce 1756 ECB :
4008 rhaas 1757 CBC 511890 : if (locallock == NULL)
1758 511678 : return;
4008 rhaas 1759 ECB :
4008 rhaas 1760 CBC 212 : fasthashcode = FastPathStrongLockHashPartition(locallock->hashcode);
2062 peter_e 1761 212 : Assert(locallock->holdsStrongLockCount == true);
4008 rhaas 1762 212 : SpinLockAcquire(&FastPathStrongRelationLocks->mutex);
3289 rhaas 1763 GIC 212 : Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
4008 1764 212 : FastPathStrongRelationLocks->count[fasthashcode]--;
2062 peter_e 1765 212 : locallock->holdsStrongLockCount = false;
4008 rhaas 1766 212 : StrongLockInProgress = NULL;
1767 212 : SpinLockRelease(&FastPathStrongRelationLocks->mutex);
1768 : }
1769 :
1770 : /*
1771 : * GrantAwaitedLock -- call GrantLockLocal for the lock we are doing
1772 : * WaitOnLock on.
1773 : *
1774 : * proc.c needs this for the case where we are booted off the lock by
1775 : * timeout, but discover that someone granted us the lock anyway.
6799 tgl 1776 ECB : *
1777 : * We could just export GrantLockLocal, but that would require including
1778 : * resowner.h in lock.h, which creates circularity.
1779 : */
1780 : void
6799 tgl 1781 GIC 985 : GrantAwaitedLock(void)
1782 : {
1783 985 : GrantLockLocal(awaitedLock, awaitedOwner);
8993 scrappy 1784 985 : }
1785 :
1786 : /*
1787 : * MarkLockClear -- mark an acquired lock as "clear"
1788 : *
1675 tgl 1789 ECB : * This means that we know we have absorbed all sinval messages that other
1790 : * sessions generated before we acquired this lock, and so we can confidently
1791 : * assume we know about any catalog changes protected by this lock.
1792 : */
1793 : void
1675 tgl 1794 GIC 25331040 : MarkLockClear(LOCALLOCK *locallock)
1795 : {
1796 25331040 : Assert(locallock->nLocks > 0);
1797 25331040 : locallock->lockCleared = true;
1798 25331040 : }
1799 :
1800 : /*
1801 : * WaitOnLock -- wait to acquire a lock
1802 : *
1803 : * Caller must have set MyProc->heldLocks to reflect locks already held
6508 tgl 1804 ECB : * on the lockable object by this process.
1805 : *
6328 1806 : * The appropriate partition lock must be held at entry.
8143 1807 : */
1808 : static void
6328 tgl 1809 GIC 1030 : WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
1810 : {
1811 1030 : LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD(*locallock);
7069 bruce 1812 1030 : LockMethod lockMethodTable = LockMethods[lockmethodid];
1813 :
6799 tgl 1814 ECB : LOCK_PRINT("WaitOnLock: sleeping on lock",
1815 : locallock->lock, locallock->tag.mode);
1816 :
1817 : /* adjust the process title to indicate that it's waiting */
48 drowley 1818 GNC 1030 : set_ps_display_suffix("waiting");
1819 :
6799 tgl 1820 GIC 1030 : awaitedLock = locallock;
1821 1030 : awaitedOwner = owner;
1822 :
8081 bruce 1823 ECB : /*
1824 : * NOTE: Think not to put any shared-state cleanup after the call to
6385 1825 : * ProcSleep, in either the normal or failure path. The lock state must
1826 : * be fully set by the lock grantor, or by CheckDeadLock if we give up
1827 : * waiting for the lock. This is necessary because of the possibility
1828 : * that a cancel/die interrupt will interrupt ProcSleep after someone else
1829 : * grants us the lock, but before we've noticed it. Hence, after granting,
1830 : * the locktable state must fully reflect the fact that we own the lock;
5545 tgl 1831 : * we can't do additional work on return.
1832 : *
1833 : * We can and do use a PG_TRY block to try to clean up after failure, but
5050 bruce 1834 : * this still has a major limitation: elog(FATAL) can occur while waiting
1835 : * (eg, a "die" interrupt), and then control won't come back here. So all
1836 : * cleanup of essential state should happen in LockErrorCleanup, not here.
1837 : * We can use PG_TRY to clear the "waiting" status flags, since doing that
1838 : * is unimportant if the process exits.
1839 : */
5545 tgl 1840 CBC 1030 : PG_TRY();
1841 : {
1026 peter 1842 GIC 1030 : if (ProcSleep(locallock, lockMethodTable) != PROC_WAIT_STATUS_OK)
1843 : {
5545 tgl 1844 ECB : /*
1845 : * We failed as a result of a deadlock, see CheckDeadLock(). Quit
1846 : * now.
1847 : */
5545 tgl 1848 GIC 5 : awaitedLock = NULL;
5545 tgl 1849 ECB : LOCK_PRINT("WaitOnLock: aborting on lock",
1850 : locallock->lock, locallock->tag.mode);
5545 tgl 1851 GIC 5 : LWLockRelease(LockHashPartitionLock(locallock->hashcode));
8120 tgl 1852 ECB :
1853 : /*
5545 1854 : * Now that we aren't holding the partition lock, we can give an
1855 : * error report including details about the detected deadlock.
1856 : */
5545 tgl 1857 GIC 5 : DeadLockReport();
1858 : /* not reached */
5545 tgl 1859 ECB : }
1860 : }
5545 tgl 1861 GIC 42 : PG_CATCH();
1862 : {
4008 rhaas 1863 ECB : /* In this path, awaitedLock remains set until LockErrorCleanup */
1864 :
1865 : /* reset ps display to remove the suffix */
48 drowley 1866 GNC 42 : set_ps_display_remove_suffix();
1867 :
1868 : /* and propagate the error */
5545 tgl 1869 GIC 42 : PG_RE_THROW();
1870 : }
1871 983 : PG_END_TRY();
9345 bruce 1872 ECB :
6799 tgl 1873 GIC 983 : awaitedLock = NULL;
6799 tgl 1874 ECB :
1875 : /* reset ps display to remove the suffix */
48 drowley 1876 GNC 983 : set_ps_display_remove_suffix();
8344 peter_e 1877 ECB :
6799 tgl 1878 : LOCK_PRINT("WaitOnLock: wakeup on lock",
1879 : locallock->lock, locallock->tag.mode);
9770 scrappy 1880 CBC 983 : }
1881 :
1882 : /*
6204 tgl 1883 ECB : * Remove a proc from the wait-queue it is on (caller must know it is on one).
1884 : * This is only used when the proc has failed to get the lock, so we set its
1885 : * waitStatus to PROC_WAIT_STATUS_ERROR.
8109 1886 : *
6204 1887 : * Appropriate partition lock must be held by caller. Also, caller is
1888 : * responsible for signaling the proc if needed.
8109 1889 : *
6613 1890 : * NB: this does not clean up any locallock object that may exist for the lock.
1891 : */
8109 1892 : void
6104 tgl 1893 CBC 45 : RemoveFromWaitQueue(PGPROC *proc, uint32 hashcode)
1894 : {
8053 bruce 1895 GIC 45 : LOCK *waitLock = proc->waitLock;
6613 tgl 1896 CBC 45 : PROCLOCK *proclock = proc->waitProcLock;
8053 bruce 1897 45 : LOCKMODE lockmode = proc->waitLockMode;
6613 tgl 1898 45 : LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*waitLock);
1899 :
1900 : /* Make sure proc is waiting */
1026 peter 1901 GIC 45 : Assert(proc->waitStatus == PROC_WAIT_STATUS_WAITING);
5271 tgl 1902 45 : Assert(proc->links.next != NULL);
8109 1903 45 : Assert(waitLock);
81 andres 1904 GNC 45 : Assert(!dclist_is_empty(&waitLock->waitProcs));
6330 tgl 1905 GIC 45 : Assert(0 < lockmethodid && lockmethodid < lengthof(LockMethods));
1906 :
8109 tgl 1907 ECB : /* Remove proc from lock's wait queue */
81 andres 1908 GNC 45 : dclist_delete_from(&waitLock->waitProcs, &proc->links);
8109 tgl 1909 ECB :
1910 : /* Undo increments of request counts by waiting process */
8109 tgl 1911 GIC 45 : Assert(waitLock->nRequested > 0);
1912 45 : Assert(waitLock->nRequested > proc->waitLock->nGranted);
1913 45 : waitLock->nRequested--;
1914 45 : Assert(waitLock->requested[lockmode] > 0);
1915 45 : waitLock->requested[lockmode]--;
1916 : /* don't forget to clear waitMask bit if appropriate */
1917 45 : if (waitLock->granted[lockmode] == waitLock->requested[lockmode])
7069 bruce 1918 44 : waitLock->waitMask &= LOCKBIT_OFF(lockmode);
1919 :
1920 : /* Clean up the proc's own state, and pass it the ok/fail signal */
8109 tgl 1921 45 : proc->waitLock = NULL;
6799 1922 45 : proc->waitProcLock = NULL;
1026 peter 1923 CBC 45 : proc->waitStatus = PROC_WAIT_STATUS_ERROR;
1924 :
6613 tgl 1925 ECB : /*
1926 : * Delete the proclock immediately if it represents no already-held locks.
1927 : * (This must happen now because if the owner of the lock decides to
1928 : * release it, and the requested/granted counts then go to zero,
1929 : * LockRelease expects there to be no remaining proclocks.) Then see if
1930 : * any other waiters for the lock can be woken up now.
1931 : */
6328 tgl 1932 GIC 45 : CleanUpLock(waitLock, proclock,
6104 1933 45 : LockMethods[lockmethodid], hashcode,
6328 tgl 1934 ECB : true);
8109 tgl 1935 GBC 45 : }
8109 tgl 1936 ECB :
9770 scrappy 1937 : /*
6330 tgl 1938 EUB : * LockRelease -- look up 'locktag' and release one 'lockmode' lock on it.
1939 : * Release a session lock if 'sessionLock' is true, else release a
1940 : * regular transaction lock.
1941 : *
1942 : * Side Effects: find any waiting processes that are now wakable,
1943 : * grant them their requested locks and awaken them.
1944 : * (We have to grant the lock here to avoid a race between
1945 : * the waking process and any new process to
1946 : * come along and request the lock.)
1947 : */
1948 : bool
6330 tgl 1949 GIC 25504916 : LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
9770 scrappy 1950 ECB : {
6330 tgl 1951 CBC 25504916 : LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
6330 tgl 1952 ECB : LockMethod lockMethodTable;
1953 : LOCALLOCKTAG localtag;
6799 1954 : LOCALLOCK *locallock;
1955 : LOCK *lock;
1956 : PROCLOCK *proclock;
1957 : LWLock *partitionLock;
1958 : bool wakeupNeeded;
1959 :
6330 tgl 1960 GIC 25504916 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
6330 tgl 1961 LBC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
6330 tgl 1962 GIC 25504916 : lockMethodTable = LockMethods[lockmethodid];
6330 tgl 1963 CBC 25504916 : if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
6330 tgl 1964 UIC 0 : elog(ERROR, "unrecognized lock mode: %d", lockmode);
6330 tgl 1965 ECB :
1966 : #ifdef LOCK_DEBUG
1967 : if (LOCK_DEBUG_ENABLED(locktag))
1968 : elog(LOG, "LockRelease: lock [%u,%u] %s",
1969 : locktag->locktag_field1, locktag->locktag_field2,
1970 : lockMethodTable->lockModeNames[lockmode]);
1971 : #endif
9676 scrappy 1972 :
1973 : /*
1974 : * Find the LOCALLOCK entry for this lock and lockmode
1975 : */
2118 tgl 1976 GIC 25504916 : MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
6799 tgl 1977 CBC 25504916 : localtag.lock = *locktag;
1978 25504916 : localtag.mode = lockmode;
1979 :
6330 1980 25504916 : locallock = (LOCALLOCK *) hash_search(LockMethodLocalHash,
1981 : &localtag,
6799 tgl 1982 ECB : HASH_FIND, NULL);
1983 :
9345 bruce 1984 : /*
1985 : * let the caller print its own error message, too. Do not ereport(ERROR).
1986 : */
6799 tgl 1987 CBC 25504916 : if (!locallock || locallock->nLocks <= 0)
1988 : {
1989 13 : elog(WARNING, "you don't own a lock of type %s",
6330 tgl 1990 ECB : lockMethodTable->lockModeNames[lockmode]);
2062 peter_e 1991 GIC 13 : return false;
9770 scrappy 1992 ECB : }
9345 bruce 1993 :
8993 scrappy 1994 : /*
1995 : * Decrease the count for the resource owner.
1996 : */
1997 : {
6799 tgl 1998 GIC 25504903 : LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
6799 tgl 1999 ECB : ResourceOwner owner;
2000 : int i;
2001 :
3992 2002 : /* Identify owner for lock */
3992 tgl 2003 GIC 25504903 : if (sessionLock)
6799 tgl 2004 CBC 57777 : owner = NULL;
2005 : else
3992 tgl 2006 GIC 25447126 : owner = CurrentResourceOwner;
2007 :
6799 2008 25505854 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
2009 : {
2010 25505842 : if (lockOwners[i].owner == owner)
2011 : {
6799 tgl 2012 CBC 25504891 : Assert(lockOwners[i].nLocks > 0);
6799 tgl 2013 GIC 25504891 : if (--lockOwners[i].nLocks == 0)
6799 tgl 2014 ECB : {
3944 heikki.linnakangas 2015 CBC 24898131 : if (owner != NULL)
3944 heikki.linnakangas 2016 GIC 24840378 : ResourceOwnerForgetLock(owner, locallock);
2017 : /* compact out unused slot */
6799 tgl 2018 24898131 : locallock->numLockOwners--;
2019 24898131 : if (i < locallock->numLockOwners)
2020 52 : lockOwners[i] = lockOwners[locallock->numLockOwners];
2021 : }
2022 25504891 : break;
2023 : }
6799 tgl 2024 ECB : }
6799 tgl 2025 GIC 25504903 : if (i < 0)
2026 : {
6799 tgl 2027 ECB : /* don't release a lock belonging to another owner */
6799 tgl 2028 CBC 12 : elog(WARNING, "you don't own a lock of type %s",
2029 : lockMethodTable->lockModeNames[lockmode]);
2062 peter_e 2030 GIC 12 : return false;
2031 : }
2032 : }
2033 :
2034 : /*
2035 : * Decrease the total local count. If we're still holding the lock, we're
6385 bruce 2036 ECB : * done.
6799 tgl 2037 : */
6799 tgl 2038 GIC 25504891 : locallock->nLocks--;
6799 tgl 2039 ECB :
6799 tgl 2040 CBC 25504891 : if (locallock->nLocks > 0)
2062 peter_e 2041 GIC 824107 : return true;
6799 tgl 2042 ECB :
1675 2043 : /*
2044 : * At this point we can no longer suppose we are clear of invalidation
2045 : * messages related to this lock. Although we'll delete the LOCALLOCK
2046 : * object before any intentional return from this routine, it seems worth
2047 : * the trouble to explicitly reset lockCleared right now, just in case
2048 : * some error prevents us from deleting the LOCALLOCK.
2049 : */
1675 tgl 2050 CBC 24680784 : locallock->lockCleared = false;
2051 :
3966 rhaas 2052 ECB : /* Attempt fast release of any lock eligible for the fast path. */
3420 tgl 2053 GIC 24680784 : if (EligibleForRelationFastPath(locktag, lockmode) &&
2054 23038994 : FastPathLocalUseCount > 0)
2055 : {
2056 : bool released;
2057 :
2058 : /*
2059 : * We might not find the lock here, even if we originally entered it
2060 : * here. Another backend may have moved it to the main table.
2061 : */
1059 tgl 2062 CBC 22238109 : LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE);
4282 rhaas 2063 22238109 : released = FastPathUnGrantRelationLock(locktag->locktag_field2,
2064 : lockmode);
1059 tgl 2065 GIC 22238109 : LWLockRelease(&MyProc->fpInfoLock);
4334 rhaas 2066 22238109 : if (released)
4334 rhaas 2067 ECB : {
4334 rhaas 2068 CBC 21494485 : RemoveLocalLock(locallock);
2062 peter_e 2069 GIC 21494485 : return true;
2070 : }
2071 : }
2072 :
6799 tgl 2073 ECB : /*
6799 tgl 2074 EUB : * Otherwise we've got to mess with the shared lock table.
6799 tgl 2075 ECB : */
6104 tgl 2076 GIC 3186299 : partitionLock = LockHashPartitionLock(locallock->hashcode);
6799 tgl 2077 ECB :
6328 tgl 2078 CBC 3186299 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
6799 tgl 2079 ECB :
2080 : /*
2081 : * Normally, we don't need to re-find the lock or proclock, since we kept
2082 : * their addresses in the locallock table, and they couldn't have been
4334 rhaas 2083 : * removed while we were holding a lock on them. But it's possible that
3420 tgl 2084 EUB : * the lock was taken fast-path and has since been moved to the main hash
2085 : * table by another backend, in which case we will need to look up the
2086 : * objects here. We assume the lock field is NULL if so.
6799 tgl 2087 ECB : */
6799 tgl 2088 GIC 3186299 : lock = locallock->lock;
4334 rhaas 2089 3186299 : if (!lock)
2090 : {
2091 : PROCLOCKTAG proclocktag;
2092 :
3966 2093 3 : Assert(EligibleForRelationFastPath(locktag, lockmode));
4334 rhaas 2094 CBC 3 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
2095 : locktag,
2096 : locallock->hashcode,
4334 rhaas 2097 EUB : HASH_FIND,
3420 tgl 2098 : NULL);
3420 tgl 2099 GIC 3 : if (!lock)
3420 tgl 2100 UBC 0 : elog(ERROR, "failed to re-find shared lock object");
4334 rhaas 2101 GBC 3 : locallock->lock = lock;
2102 :
4334 rhaas 2103 GIC 3 : proclocktag.myLock = lock;
2104 3 : proclocktag.myProc = MyProc;
2105 3 : locallock->proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash,
2106 : &proclocktag,
3420 tgl 2107 ECB : HASH_FIND,
2108 : NULL);
3420 tgl 2109 CBC 3 : if (!locallock->proclock)
3420 tgl 2110 UIC 0 : elog(ERROR, "failed to re-find shared proclock object");
2111 : }
2112 : LOCK_PRINT("LockRelease: found", lock, lockmode);
6799 tgl 2113 CBC 3186299 : proclock = locallock->proclock;
2114 : PROCLOCK_PRINT("LockRelease: found", proclock);
8993 scrappy 2115 ECB :
2116 : /*
2117 : * Double-check that we are actually holding a lock of the type we want to
2118 : * release.
2119 : */
6799 tgl 2120 GIC 3186299 : if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
2121 : {
2122 : PROCLOCK_PRINT("LockRelease: WRONGTYPE", proclock);
6328 tgl 2123 UIC 0 : LWLockRelease(partitionLock);
7199 2124 0 : elog(WARNING, "you don't own a lock of type %s",
2125 : lockMethodTable->lockModeNames[lockmode]);
6799 2126 0 : RemoveLocalLock(locallock);
2062 peter_e 2127 0 : return false;
8993 scrappy 2128 ECB : }
2129 :
2130 : /*
2131 : * Do the releasing. CleanUpLock will waken any now-wakable waiters.
2132 : */
6534 tgl 2133 GIC 3186299 : wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
2134 :
6328 2135 3186299 : CleanUpLock(lock, proclock,
2136 : lockMethodTable, locallock->hashcode,
6328 tgl 2137 ECB : wakeupNeeded);
2138 :
6328 tgl 2139 CBC 3186299 : LWLockRelease(partitionLock);
6799 tgl 2140 EUB :
6799 tgl 2141 CBC 3186299 : RemoveLocalLock(locallock);
2062 peter_e 2142 GIC 3186299 : return true;
2143 : }
2144 :
2145 : /*
2146 : * LockReleaseAll -- Release all locks of the specified lock method that
2147 : * are held by the current process.
2148 : *
2149 : * Well, not necessarily *all* locks. The available behaviors are:
2150 : * allLocks == true: release all locks including session locks.
2151 : * allLocks == false: release all non-session locks.
2152 : */
2153 : void
6508 tgl 2154 CBC 984161 : LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks)
9770 scrappy 2155 ECB : {
2156 : HASH_SEQ_STATUS status;
7069 bruce 2157 : LockMethod lockMethodTable;
2158 : int i,
2159 : numLockModes;
2160 : LOCALLOCK *locallock;
2161 : LOCK *lock;
2162 : int partition;
4334 rhaas 2163 GIC 984161 : bool have_fast_path_lwlock = false;
2164 :
6330 tgl 2165 984161 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
6330 tgl 2166 LBC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
6330 tgl 2167 GIC 984161 : lockMethodTable = LockMethods[lockmethodid];
6330 tgl 2168 ECB :
2169 : #ifdef LOCK_DEBUG
2170 : if (*(lockMethodTable->trace_flag))
2171 : elog(LOG, "LockReleaseAll: lockmethod=%d", lockmethodid);
2172 : #endif
2173 :
2174 : /*
3260 bruce 2175 : * Get rid of our fast-path VXID lock, if appropriate. Note that this is
2176 : * the only way that the lock we hold on our own VXID can ever get
4266 rhaas 2177 : * released: it is always and only released when a toplevel transaction
2178 : * ends.
2179 : */
4266 rhaas 2180 GIC 984161 : if (lockmethodid == DEFAULT_LOCKMETHOD)
2181 486486 : VirtualXactLockTableCleanup();
4266 rhaas 2182 ECB :
7570 bruce 2183 CBC 984161 : numLockModes = lockMethodTable->numLockModes;
2184 :
2185 : /*
2186 : * First we run through the locallock table and get rid of unwanted
2187 : * entries, then we scan the process's proclocks and get rid of those. We
2188 : * do this separately because we may have multiple locallock entries
2189 : * pointing to the same proclock, and we daren't end up with any dangling
3420 tgl 2190 ECB : * pointers. Fast-path locks are cleaned up during the locallock table
2191 : * scan, though.
6799 2192 : */
6330 tgl 2193 GIC 984161 : hash_seq_init(&status, LockMethodLocalHash);
2194 :
6799 tgl 2195 CBC 2557813 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2196 : {
3966 rhaas 2197 ECB : /*
2198 : * If the LOCALLOCK entry is unused, we must've run out of shared
2199 : * memory while trying to set up this lock. Just forget the local
2200 : * entry.
2201 : */
3966 rhaas 2202 GIC 1573652 : if (locallock->nLocks == 0)
6799 tgl 2203 ECB : {
3966 rhaas 2204 CBC 45 : RemoveLocalLock(locallock);
2205 45 : continue;
2206 : }
2207 :
3966 rhaas 2208 ECB : /* Ignore items that are not of the lockmethod to be removed */
3966 rhaas 2209 CBC 1573607 : if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
3966 rhaas 2210 GIC 59108 : continue;
3966 rhaas 2211 ECB :
2212 : /*
2213 : * If we are asked to release all locks, we can just zap the entry.
2214 : * Otherwise, must scan to see if there are session locks. We assume
2215 : * there is at most one lockOwners entry for session locks.
2216 : */
3966 rhaas 2217 GIC 1514499 : if (!allLocks)
2218 : {
2219 1456898 : LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
2220 :
3944 heikki.linnakangas 2221 ECB : /* If session lock is above array position 0, move it down to 0 */
3602 bruce 2222 CBC 2954501 : for (i = 0; i < locallock->numLockOwners; i++)
4334 rhaas 2223 ECB : {
3966 rhaas 2224 GIC 1497603 : if (lockOwners[i].owner == NULL)
2225 59025 : lockOwners[0] = lockOwners[i];
2226 : else
3944 heikki.linnakangas 2227 CBC 1438578 : ResourceOwnerForgetLock(lockOwners[i].owner, locallock);
3966 rhaas 2228 EUB : }
2229 :
3966 rhaas 2230 GIC 1456898 : if (locallock->numLockOwners > 0 &&
2231 1456898 : lockOwners[0].owner == NULL &&
2232 59025 : lockOwners[0].nLocks > 0)
2233 : {
2234 : /* Fix the locallock to show just the session locks */
2235 59025 : locallock->nLocks = lockOwners[0].nLocks;
2236 59025 : locallock->numLockOwners = 1;
2237 : /* We aren't deleting this locallock, so done */
4334 rhaas 2238 CBC 59025 : continue;
2239 : }
3944 heikki.linnakangas 2240 ECB : else
3944 heikki.linnakangas 2241 CBC 1397873 : locallock->numLockOwners = 0;
2242 : }
2243 :
2244 : /*
3966 rhaas 2245 ECB : * If the lock or proclock pointers are NULL, this lock was taken via
3420 tgl 2246 : * the relation fast-path (and is not known to have been transferred).
2247 : */
3966 rhaas 2248 CBC 1455474 : if (locallock->proclock == NULL || locallock->lock == NULL)
2249 955 : {
3966 rhaas 2250 GIC 602057 : LOCKMODE lockmode = locallock->tag.mode;
2251 : Oid relid;
2252 :
2253 : /* Verify that a fast-path lock is what we've got. */
2254 602057 : if (!EligibleForRelationFastPath(&locallock->tag.lock, lockmode))
4334 rhaas 2255 UIC 0 : elog(PANIC, "locallock table corrupted");
2256 :
4334 rhaas 2257 ECB : /*
2258 : * If we don't currently hold the LWLock that protects our
2259 : * fast-path data structures, we must acquire it before attempting
2260 : * to release the lock via the fast-path. We will continue to
2261 : * hold the LWLock until we're done scanning the locallock table,
2262 : * unless we hit a transferred fast-path lock. (XXX is this
2263 : * really such a good idea? There could be a lot of entries ...)
2264 : */
4334 rhaas 2265 GIC 602057 : if (!have_fast_path_lwlock)
2266 : {
1059 tgl 2267 CBC 219537 : LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE);
4334 rhaas 2268 GIC 219537 : have_fast_path_lwlock = true;
4334 rhaas 2269 ECB : }
2270 :
2271 : /* Attempt fast-path release. */
4334 rhaas 2272 GIC 602057 : relid = locallock->tag.lock.locktag_field2;
4282 2273 602057 : if (FastPathUnGrantRelationLock(relid, lockmode))
4334 rhaas 2274 ECB : {
4334 rhaas 2275 CBC 601102 : RemoveLocalLock(locallock);
4334 rhaas 2276 GIC 601102 : continue;
2277 : }
4334 rhaas 2278 ECB :
2279 : /*
2280 : * Our lock, originally taken via the fast path, has been
2281 : * transferred to the main lock table. That's going to require
2282 : * some extra work, so release our fast-path lock before starting.
2283 : */
1059 tgl 2284 GIC 955 : LWLockRelease(&MyProc->fpInfoLock);
4334 rhaas 2285 955 : have_fast_path_lwlock = false;
2286 :
2287 : /*
4334 rhaas 2288 ECB : * Now dump the lock. We haven't got a pointer to the LOCK or
2289 : * PROCLOCK in this case, so we have to handle this a bit
2290 : * differently than a normal lock release. Unfortunately, this
2291 : * requires an extra LWLock acquire-and-release cycle on the
2292 : * partitionLock, but hopefully it shouldn't happen often.
2293 : */
4334 rhaas 2294 CBC 955 : LockRefindAndRelease(lockMethodTable, MyProc,
2295 : &locallock->tag.lock, lockmode, false);
6799 tgl 2296 GIC 955 : RemoveLocalLock(locallock);
2297 955 : continue;
2298 : }
2299 :
2300 : /* Mark the proclock to show we need to release this lockmode */
6508 2301 853417 : if (locallock->nLocks > 0)
2302 853417 : locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
2303 :
2304 : /* And remove the locallock hashtable entry */
6799 2305 853417 : RemoveLocalLock(locallock);
2306 : }
2307 :
2308 : /* Done with the fast-path data structures */
4334 rhaas 2309 984161 : if (have_fast_path_lwlock)
1059 tgl 2310 218582 : LWLockRelease(&MyProc->fpInfoLock);
2311 :
2312 : /*
2313 : * Now, scan each lock partition separately.
2314 : */
6328 tgl 2315 CBC 16730737 : for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
6328 tgl 2316 ECB : {
2317 : LWLock *partitionLock;
81 andres 2318 GNC 15746576 : dlist_head *procLocks = &MyProc->myProcLocks[partition];
2319 : dlist_mutable_iter proclock_iter;
9345 bruce 2320 ECB :
3359 rhaas 2321 GIC 15746576 : partitionLock = LockHashPartitionLockByIndex(partition);
3359 rhaas 2322 ECB :
3419 tgl 2323 : /*
2324 : * If the proclock list for this partition is empty, we can skip
2325 : * acquiring the partition lock. This optimization is trickier than
2326 : * it looks, because another backend could be in process of adding
2327 : * something to our proclock list due to promoting one of our
2328 : * fast-path locks. However, any such lock must be one that we
2329 : * decided not to delete above, so it's okay to skip it again now;
2330 : * we'd just decide not to delete it again. We must, however, be
2331 : * careful to re-fetch the list header once we've acquired the
2332 : * partition lock, to be sure we have a valid, up-to-date pointer.
2333 : * (There is probably no significant risk if pointer fetch/store is
2334 : * atomic, but we don't wish to assume that.)
2335 : *
2336 : * XXX This argument assumes that the locallock table correctly
2337 : * represents all of our fast-path locks. While allLocks mode
2338 : * guarantees to clean up all of our normal locks regardless of the
2339 : * locallock situation, we lose that guarantee for fast-path locks.
2340 : * This is not ideal.
2341 : */
81 andres 2342 GNC 15746576 : if (dlist_is_empty(procLocks))
6328 tgl 2343 GIC 14970807 : continue; /* needn't examine this partition */
2344 :
6328 tgl 2345 CBC 775769 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
8143 tgl 2346 ECB :
81 andres 2347 GNC 1717023 : dlist_foreach_modify(proclock_iter, procLocks)
6328 tgl 2348 ECB : {
81 andres 2349 GNC 941254 : PROCLOCK *proclock = dlist_container(PROCLOCK, procLink, proclock_iter.cur);
6328 tgl 2350 CBC 941254 : bool wakeupNeeded = false;
9345 bruce 2351 ECB :
6104 tgl 2352 GIC 941254 : Assert(proclock->tag.myProc == MyProc);
9345 bruce 2353 ECB :
6104 tgl 2354 CBC 941254 : lock = proclock->tag.myLock;
2355 :
2356 : /* Ignore items that are not of the lockmethod to be removed */
6328 2357 941254 : if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
3419 2358 59105 : continue;
2359 :
2360 : /*
6328 tgl 2361 ECB : * In allLocks mode, force release of all locks even if locallock
2362 : * table had problems
2363 : */
6328 tgl 2364 CBC 882149 : if (allLocks)
6328 tgl 2365 GIC 36933 : proclock->releaseMask = proclock->holdMask;
6328 tgl 2366 ECB : else
6328 tgl 2367 GIC 845216 : Assert((proclock->releaseMask & ~proclock->holdMask) == 0);
2368 :
2369 : /*
6328 tgl 2370 ECB : * Ignore items that have nothing to be released, unless they have
2371 : * holdMask == 0 and are therefore recyclable
2372 : */
6328 tgl 2373 GIC 882149 : if (proclock->releaseMask == 0 && proclock->holdMask != 0)
3419 2374 58430 : continue;
2375 :
2376 : PROCLOCK_PRINT("LockReleaseAll", proclock);
6328 tgl 2377 ECB : LOCK_PRINT("LockReleaseAll", lock, 0);
6328 tgl 2378 GIC 823719 : Assert(lock->nRequested >= 0);
2379 823719 : Assert(lock->nGranted >= 0);
2380 823719 : Assert(lock->nGranted <= lock->nRequested);
2381 823719 : Assert((proclock->holdMask & ~lock->grantMask) == 0);
2382 :
2383 : /*
6328 tgl 2384 ECB : * Release the previously-marked lock modes
2385 : */
6328 tgl 2386 GIC 7413471 : for (i = 1; i <= numLockModes; i++)
2387 : {
2388 6589752 : if (proclock->releaseMask & LOCKBIT_ON(i))
6328 tgl 2389 CBC 853417 : wakeupNeeded |= UnGrantLock(lock, i, proclock,
6328 tgl 2390 EUB : lockMethodTable);
2391 : }
6328 tgl 2392 CBC 823719 : Assert((lock->nRequested >= 0) && (lock->nGranted >= 0));
6328 tgl 2393 GIC 823719 : Assert(lock->nGranted <= lock->nRequested);
6328 tgl 2394 ECB : LOCK_PRINT("LockReleaseAll: updated", lock, 0);
2395 :
6328 tgl 2396 GIC 823719 : proclock->releaseMask = 0;
9345 bruce 2397 ECB :
6328 tgl 2398 : /* CleanUpLock will wake up waiters if needed. */
6328 tgl 2399 GIC 823719 : CleanUpLock(lock, proclock,
6104 tgl 2400 ECB : lockMethodTable,
6104 tgl 2401 GIC 823719 : LockTagHashCode(&lock->tag),
6328 tgl 2402 ECB : wakeupNeeded);
2403 : } /* loop over PROCLOCKs within this partition */
2404 :
6328 tgl 2405 GIC 775769 : LWLockRelease(partitionLock);
2406 : } /* loop over partitions */
2407 :
2408 : #ifdef LOCK_DEBUG
2409 : if (*(lockMethodTable->trace_flag))
2410 : elog(LOG, "LockReleaseAll done");
2411 : #endif
9770 scrappy 2412 984161 : }
2413 :
3992 tgl 2414 ECB : /*
2415 : * LockReleaseSession -- Release all session locks of the specified lock method
2416 : * that are held by the current process.
2417 : */
2418 : void
3992 tgl 2419 GIC 119 : LockReleaseSession(LOCKMETHODID lockmethodid)
2420 : {
3992 tgl 2421 ECB : HASH_SEQ_STATUS status;
2422 : LOCALLOCK *locallock;
2423 :
3992 tgl 2424 CBC 119 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
3992 tgl 2425 UIC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
2426 :
3992 tgl 2427 GIC 119 : hash_seq_init(&status, LockMethodLocalHash);
2428 :
2429 226 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3992 tgl 2430 ECB : {
2431 : /* Ignore items that are not of the specified lock method */
3992 tgl 2432 GIC 107 : if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
3992 tgl 2433 CBC 10 : continue;
2434 :
3992 tgl 2435 GIC 97 : ReleaseLockIfHeld(locallock, true);
2436 : }
2437 119 : }
2438 :
2439 : /*
2440 : * LockReleaseCurrentOwner
2441 : * Release all locks belonging to CurrentResourceOwner
2442 : *
2443 : * If the caller knows what those locks are, it can pass them as an array.
2444 : * That speeds up the call significantly, when a lot of locks are held.
2445 : * Otherwise, pass NULL for locallocks, and we'll traverse through our hash
2446 : * table to find them.
2447 : */
2448 : void
3944 heikki.linnakangas 2449 CBC 4600 : LockReleaseCurrentOwner(LOCALLOCK **locallocks, int nlocks)
2450 : {
3944 heikki.linnakangas 2451 GIC 4600 : if (locallocks == NULL)
2452 : {
2453 : HASH_SEQ_STATUS status;
2454 : LOCALLOCK *locallock;
2455 :
3944 heikki.linnakangas 2456 CBC 4 : hash_seq_init(&status, LockMethodLocalHash);
6799 tgl 2457 ECB :
3944 heikki.linnakangas 2458 GIC 265 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3944 heikki.linnakangas 2459 CBC 261 : ReleaseLockIfHeld(locallock, false);
2460 : }
2461 : else
6799 tgl 2462 ECB : {
3602 bruce 2463 : int i;
2464 :
3944 heikki.linnakangas 2465 CBC 7039 : for (i = nlocks - 1; i >= 0; i--)
3944 heikki.linnakangas 2466 GIC 2443 : ReleaseLockIfHeld(locallocks[i], false);
4433 itagaki.takahiro 2467 ECB : }
4433 itagaki.takahiro 2468 CBC 4600 : }
2469 :
2470 : /*
2471 : * ReleaseLockIfHeld
2472 : * Release any session-level locks on this lockable object if sessionLock
2473 : * is true; else, release any locks held by CurrentResourceOwner.
3992 tgl 2474 ECB : *
2475 : * It is tempting to pass this a ResourceOwner pointer (or NULL for session
2476 : * locks), but without refactoring LockRelease() we cannot support releasing
2477 : * locks belonging to resource owners other than CurrentResourceOwner.
2478 : * If we were to refactor, it'd be a good idea to fix it so we don't have to
2479 : * do a hashtable lookup of the locallock, too. However, currently this
3992 tgl 2480 EUB : * function isn't used heavily enough to justify refactoring for its
2481 : * convenience.
2482 : */
2483 : static void
3992 tgl 2484 CBC 2801 : ReleaseLockIfHeld(LOCALLOCK *locallock, bool sessionLock)
2485 : {
3992 tgl 2486 ECB : ResourceOwner owner;
4433 itagaki.takahiro 2487 : LOCALLOCKOWNER *lockOwners;
3992 tgl 2488 : int i;
2489 :
2490 : /* Identify owner for lock (must match LockRelease!) */
3992 tgl 2491 GBC 2801 : if (sessionLock)
3992 tgl 2492 GIC 97 : owner = NULL;
3992 tgl 2493 ECB : else
3992 tgl 2494 GIC 2704 : owner = CurrentResourceOwner;
2495 :
3992 tgl 2496 ECB : /* Scan to see if there are any locks belonging to the target owner */
4433 itagaki.takahiro 2497 GIC 2801 : lockOwners = locallock->lockOwners;
2498 2991 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
2499 : {
2500 2801 : if (lockOwners[i].owner == owner)
2501 : {
2502 2611 : Assert(lockOwners[i].nLocks > 0);
2503 2611 : if (lockOwners[i].nLocks < locallock->nLocks)
2504 : {
2505 : /*
2506 : * We will still hold this lock after forgetting this
2507 : * ResourceOwner.
2508 : */
4433 itagaki.takahiro 2509 CBC 669 : locallock->nLocks -= lockOwners[i].nLocks;
2510 : /* compact out unused slot */
2511 669 : locallock->numLockOwners--;
3944 heikki.linnakangas 2512 GIC 669 : if (owner != NULL)
3944 heikki.linnakangas 2513 CBC 669 : ResourceOwnerForgetLock(owner, locallock);
4433 itagaki.takahiro 2514 GIC 669 : if (i < locallock->numLockOwners)
4433 itagaki.takahiro 2515 LBC 0 : lockOwners[i] = lockOwners[locallock->numLockOwners];
2516 : }
2517 : else
2518 : {
4433 itagaki.takahiro 2519 GIC 1942 : Assert(lockOwners[i].nLocks == locallock->nLocks);
4433 itagaki.takahiro 2520 ECB : /* We want to call LockRelease just once */
4433 itagaki.takahiro 2521 GIC 1942 : lockOwners[i].nLocks = 1;
4433 itagaki.takahiro 2522 CBC 1942 : locallock->nLocks = 1;
2523 1942 : if (!LockRelease(&locallock->tag.lock,
2524 : locallock->tag.mode,
2525 : sessionLock))
3992 tgl 2526 UIC 0 : elog(WARNING, "ReleaseLockIfHeld: failed??");
2527 : }
4433 itagaki.takahiro 2528 GIC 2611 : break;
6799 tgl 2529 ECB : }
2530 : }
6799 tgl 2531 GIC 2801 : }
6799 tgl 2532 ECB :
2533 : /*
2534 : * LockReassignCurrentOwner
2535 : * Reassign all locks belonging to CurrentResourceOwner to belong
2536 : * to its parent resource owner.
2537 : *
2538 : * If the caller knows what those locks are, it can pass them as an array.
3944 heikki.linnakangas 2539 : * That speeds up the call significantly, when a lot of locks are held
2540 : * (e.g pg_dump with a large schema). Otherwise, pass NULL for locallocks,
2541 : * and we'll traverse through our hash table to find them.
2542 : */
6799 tgl 2543 : void
3944 heikki.linnakangas 2544 CBC 482124 : LockReassignCurrentOwner(LOCALLOCK **locallocks, int nlocks)
2545 : {
6799 tgl 2546 GIC 482124 : ResourceOwner parent = ResourceOwnerGetParent(CurrentResourceOwner);
2547 :
2548 482124 : Assert(parent != NULL);
2549 :
3944 heikki.linnakangas 2550 CBC 482124 : if (locallocks == NULL)
3944 heikki.linnakangas 2551 ECB : {
2552 : HASH_SEQ_STATUS status;
2553 : LOCALLOCK *locallock;
6799 tgl 2554 :
3944 heikki.linnakangas 2555 CBC 3491 : hash_seq_init(&status, LockMethodLocalHash);
3944 heikki.linnakangas 2556 ECB :
3944 heikki.linnakangas 2557 GIC 84751 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
2558 81260 : LockReassignOwner(locallock, parent);
3944 heikki.linnakangas 2559 ECB : }
2560 : else
2561 : {
3602 bruce 2562 : int i;
2563 :
3944 heikki.linnakangas 2564 GIC 1079427 : for (i = nlocks - 1; i >= 0; i--)
3944 heikki.linnakangas 2565 CBC 600794 : LockReassignOwner(locallocks[i], parent);
3944 heikki.linnakangas 2566 ECB : }
3944 heikki.linnakangas 2567 GIC 482124 : }
2568 :
2569 : /*
2570 : * Subroutine of LockReassignCurrentOwner. Reassigns a given lock belonging to
3944 heikki.linnakangas 2571 ECB : * CurrentResourceOwner to its parent.
2572 : */
2573 : static void
3944 heikki.linnakangas 2574 CBC 682054 : LockReassignOwner(LOCALLOCK *locallock, ResourceOwner parent)
3944 heikki.linnakangas 2575 ECB : {
2576 : LOCALLOCKOWNER *lockOwners;
2577 : int i;
3944 heikki.linnakangas 2578 GIC 682054 : int ic = -1;
2579 682054 : int ip = -1;
2580 :
2581 : /*
2582 : * Scan to see if there are any locks belonging to current owner or its
2583 : * parent
2584 : */
3944 heikki.linnakangas 2585 CBC 682054 : lockOwners = locallock->lockOwners;
3944 heikki.linnakangas 2586 GIC 1491583 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
2587 : {
3944 heikki.linnakangas 2588 CBC 809529 : if (lockOwners[i].owner == CurrentResourceOwner)
3944 heikki.linnakangas 2589 GIC 672779 : ic = i;
2590 136750 : else if (lockOwners[i].owner == parent)
3944 heikki.linnakangas 2591 CBC 95098 : ip = i;
2592 : }
3944 heikki.linnakangas 2593 ECB :
3944 heikki.linnakangas 2594 CBC 682054 : if (ic < 0)
3602 bruce 2595 9275 : return; /* no current locks */
2596 :
3944 heikki.linnakangas 2597 672779 : if (ip < 0)
3944 heikki.linnakangas 2598 ECB : {
2599 : /* Parent has no slot, so just give it the child's slot */
3944 heikki.linnakangas 2600 GIC 586925 : lockOwners[ic].owner = parent;
2601 586925 : ResourceOwnerRememberLock(parent, locallock);
2602 : }
2603 : else
3944 heikki.linnakangas 2604 ECB : {
2605 : /* Merge child's count with parent's */
3944 heikki.linnakangas 2606 CBC 85854 : lockOwners[ip].nLocks += lockOwners[ic].nLocks;
3944 heikki.linnakangas 2607 ECB : /* compact out unused slot */
3944 heikki.linnakangas 2608 CBC 85854 : locallock->numLockOwners--;
2609 85854 : if (ic < locallock->numLockOwners)
3944 heikki.linnakangas 2610 GIC 685 : lockOwners[ic] = lockOwners[locallock->numLockOwners];
2611 : }
2612 672779 : ResourceOwnerForgetLock(CurrentResourceOwner, locallock);
4334 rhaas 2613 EUB : }
2614 :
2615 : /*
2616 : * FastPathGrantRelationLock
2617 : * Grant lock using per-backend fast-path array, if there is space.
2618 : */
2619 : static bool
4282 rhaas 2620 GIC 22096918 : FastPathGrantRelationLock(Oid relid, LOCKMODE lockmode)
2621 : {
4334 rhaas 2622 ECB : uint32 f;
4334 rhaas 2623 GIC 22096918 : uint32 unused_slot = FP_LOCK_SLOTS_PER_BACKEND;
2624 :
4334 rhaas 2625 ECB : /* Scan for existing entry for this relid, remembering empty slot. */
4334 rhaas 2626 GIC 372805832 : for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
4334 rhaas 2627 ECB : {
4334 rhaas 2628 CBC 351647793 : if (FAST_PATH_GET_BITS(MyProc, f) == 0)
4334 rhaas 2629 GIC 304569020 : unused_slot = f;
4334 rhaas 2630 CBC 47078773 : else if (MyProc->fpRelId[f] == relid)
4334 rhaas 2631 ECB : {
4334 rhaas 2632 GIC 938879 : Assert(!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode));
4334 rhaas 2633 CBC 938879 : FAST_PATH_SET_LOCKMODE(MyProc, f, lockmode);
2634 938879 : return true;
4334 rhaas 2635 ECB : }
2636 : }
2637 :
2638 : /* If no existing entry, use any empty slot. */
4334 rhaas 2639 CBC 21158039 : if (unused_slot < FP_LOCK_SLOTS_PER_BACKEND)
2640 : {
2641 21158039 : MyProc->fpRelId[unused_slot] = relid;
4334 rhaas 2642 GIC 21158039 : FAST_PATH_SET_LOCKMODE(MyProc, unused_slot, lockmode);
2643 21158039 : ++FastPathLocalUseCount;
2644 21158039 : return true;
2645 : }
2646 :
2647 : /* No existing entry, and no empty slot. */
4334 rhaas 2648 UIC 0 : return false;
2649 : }
2650 :
2651 : /*
4282 rhaas 2652 ECB : * FastPathUnGrantRelationLock
2653 : * Release fast-path lock, if present. Update backend-private local
2654 : * use count, while we're at it.
4334 2655 : */
2656 : static bool
4282 rhaas 2657 GIC 22840166 : FastPathUnGrantRelationLock(Oid relid, LOCKMODE lockmode)
2658 : {
2659 : uint32 f;
4334 2660 22840166 : bool result = false;
2661 :
2662 22840166 : FastPathLocalUseCount = 0;
2663 388282822 : for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2664 : {
4334 rhaas 2665 CBC 365442656 : if (MyProc->fpRelId[f] == relid
4334 rhaas 2666 GIC 27758203 : && FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
4334 rhaas 2667 ECB : {
4334 rhaas 2668 GIC 22095587 : Assert(!result);
2669 22095587 : FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
4334 rhaas 2670 CBC 22095587 : result = true;
2671 : /* we continue iterating so as to update FastPathLocalUseCount */
2672 : }
4334 rhaas 2673 GIC 365442656 : if (FAST_PATH_GET_BITS(MyProc, f) != 0)
2674 52651815 : ++FastPathLocalUseCount;
2675 : }
2676 22840166 : return result;
2677 : }
2678 :
2679 : /*
2680 : * FastPathTransferRelationLocks
2681 : * Transfer locks matching the given lock tag from per-backend fast-path
2682 : * arrays to the shared hash table.
2683 : *
2684 : * Returns true if successful, false if ran out of shared memory.
2685 : */
2686 : static bool
4282 rhaas 2687 CBC 271615 : FastPathTransferRelationLocks(LockMethod lockMethodTable, const LOCKTAG *locktag,
2688 : uint32 hashcode)
4334 rhaas 2689 ECB : {
3359 rhaas 2690 CBC 271615 : LWLock *partitionLock = LockHashPartitionLock(hashcode);
3955 bruce 2691 GIC 271615 : Oid relid = locktag->locktag_field2;
2692 : uint32 i;
4334 rhaas 2693 ECB :
2694 : /*
2695 : * Every PGPROC that can potentially hold a fast-path lock is present in
2696 : * ProcGlobal->allProcs. Prepared transactions are not, but any
2697 : * outstanding fast-path locks held by prepared transactions are
2698 : * transferred to the main lock table.
2699 : */
4334 rhaas 2700 GIC 31018920 : for (i = 0; i < ProcGlobal->allProcCount; i++)
2701 : {
4334 rhaas 2702 CBC 30747305 : PGPROC *proc = &ProcGlobal->allProcs[i];
4334 rhaas 2703 ECB : uint32 f;
2704 :
1059 tgl 2705 CBC 30747305 : LWLockAcquire(&proc->fpInfoLock, LW_EXCLUSIVE);
2706 :
2707 : /*
2708 : * If the target backend isn't referencing the same database as the
3733 rhaas 2709 ECB : * lock, then we needn't examine the individual relation IDs at all;
3955 bruce 2710 : * none of them can be relevant.
4334 rhaas 2711 : *
2712 : * proc->databaseId is set at backend startup time and never changes
2713 : * thereafter, so it might be safe to perform this test before
2714 : * acquiring &proc->fpInfoLock. In particular, it's certainly safe to
1059 tgl 2715 EUB : * assume that if the target backend holds any fast-path locks, it
3955 bruce 2716 : * must have performed a memory-fencing operation (in particular, an
3260 2717 : * LWLock acquisition) since setting proc->databaseId. However, it's
2718 : * less clear that our backend is certain to have performed a memory
3260 bruce 2719 ECB : * fencing operation since the other backend set proc->databaseId. So
3955 2720 : * for now, we test it after acquiring the LWLock just to be safe.
2721 : */
3733 rhaas 2722 CBC 30747305 : if (proc->databaseId != locktag->locktag_field1)
2723 : {
1059 tgl 2724 GIC 23150998 : LWLockRelease(&proc->fpInfoLock);
4334 rhaas 2725 CBC 23150998 : continue;
2726 : }
4334 rhaas 2727 ECB :
4334 rhaas 2728 GIC 129136080 : for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
4334 rhaas 2729 ECB : {
2730 : uint32 lockmode;
2731 :
2732 : /* Look for an allocated slot matching the given relid. */
4334 rhaas 2733 GIC 121540687 : if (relid != proc->fpRelId[f] || FAST_PATH_GET_BITS(proc, f) == 0)
2734 121539773 : continue;
2735 :
2736 : /* Find or create lock object. */
2737 914 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2738 914 : for (lockmode = FAST_PATH_LOCKNUMBER_OFFSET;
2118 tgl 2739 3656 : lockmode < FAST_PATH_LOCKNUMBER_OFFSET + FAST_PATH_BITS_PER_SLOT;
4334 rhaas 2740 CBC 2742 : ++lockmode)
2741 : {
4334 rhaas 2742 ECB : PROCLOCK *proclock;
2743 :
4334 rhaas 2744 CBC 2742 : if (!FAST_PATH_CHECK_LOCKMODE(proc, f, lockmode))
2745 1776 : continue;
2746 966 : proclock = SetupLockInTable(lockMethodTable, proc, locktag,
2747 : hashcode, lockmode);
4334 rhaas 2748 GIC 966 : if (!proclock)
4334 rhaas 2749 ECB : {
4334 rhaas 2750 UIC 0 : LWLockRelease(partitionLock);
1059 tgl 2751 LBC 0 : LWLockRelease(&proc->fpInfoLock);
4334 rhaas 2752 UIC 0 : return false;
2753 : }
4334 rhaas 2754 GIC 966 : GrantLock(proclock->tag.myLock, proclock, lockmode);
2755 966 : FAST_PATH_CLEAR_LOCKMODE(proc, f, lockmode);
4334 rhaas 2756 ECB : }
4334 rhaas 2757 CBC 914 : LWLockRelease(partitionLock);
2758 :
2759 : /* No need to examine remaining slots. */
3420 tgl 2760 914 : break;
4334 rhaas 2761 ECB : }
1059 tgl 2762 GBC 7596307 : LWLockRelease(&proc->fpInfoLock);
2763 : }
4334 rhaas 2764 GIC 271615 : return true;
4334 rhaas 2765 ECB : }
2766 :
2767 : /*
2768 : * FastPathGetRelationLockEntry
2769 : * Return the PROCLOCK for a lock originally taken via the fast-path,
2770 : * transferring it to the primary lock table if necessary.
3420 tgl 2771 EUB : *
2772 : * Note: caller takes care of updating the locallock object.
4334 rhaas 2773 : */
2774 : static PROCLOCK *
4282 rhaas 2775 GIC 373 : FastPathGetRelationLockEntry(LOCALLOCK *locallock)
2776 : {
3955 bruce 2777 373 : LockMethod lockMethodTable = LockMethods[DEFAULT_LOCKMETHOD];
3955 bruce 2778 CBC 373 : LOCKTAG *locktag = &locallock->tag.lock;
2779 373 : PROCLOCK *proclock = NULL;
3359 rhaas 2780 GIC 373 : LWLock *partitionLock = LockHashPartitionLock(locallock->hashcode);
3955 bruce 2781 CBC 373 : Oid relid = locktag->locktag_field2;
2782 : uint32 f;
2783 :
1059 tgl 2784 373 : LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE);
2785 :
4334 rhaas 2786 GIC 5956 : for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
4334 rhaas 2787 ECB : {
2788 : uint32 lockmode;
2789 :
2790 : /* Look for an allocated slot matching the given relid. */
4334 rhaas 2791 GIC 5948 : if (relid != MyProc->fpRelId[f] || FAST_PATH_GET_BITS(MyProc, f) == 0)
2792 5583 : continue;
2793 :
2794 : /* If we don't have a lock of the given mode, forget it! */
2795 365 : lockmode = locallock->tag.mode;
4334 rhaas 2796 CBC 365 : if (!FAST_PATH_CHECK_LOCKMODE(MyProc, f, lockmode))
4334 rhaas 2797 UIC 0 : break;
4334 rhaas 2798 ECB :
2799 : /* Find or create lock object. */
4334 rhaas 2800 GIC 365 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
2801 :
2802 365 : proclock = SetupLockInTable(lockMethodTable, MyProc, locktag,
4334 rhaas 2803 ECB : locallock->hashcode, lockmode);
4334 rhaas 2804 GBC 365 : if (!proclock)
2805 : {
3743 tgl 2806 LBC 0 : LWLockRelease(partitionLock);
1059 2807 0 : LWLockRelease(&MyProc->fpInfoLock);
4334 rhaas 2808 UIC 0 : ereport(ERROR,
4334 rhaas 2809 ECB : (errcode(ERRCODE_OUT_OF_MEMORY),
2810 : errmsg("out of shared memory"),
3955 bruce 2811 : errhint("You might need to increase max_locks_per_transaction.")));
2812 : }
4334 rhaas 2813 GIC 365 : GrantLock(proclock->tag.myLock, proclock, lockmode);
2814 365 : FAST_PATH_CLEAR_LOCKMODE(MyProc, f, lockmode);
2815 :
4334 rhaas 2816 CBC 365 : LWLockRelease(partitionLock);
3420 tgl 2817 EUB :
3420 tgl 2818 ECB : /* No need to examine remaining slots. */
3420 tgl 2819 GIC 365 : break;
2820 : }
4334 rhaas 2821 ECB :
1059 tgl 2822 GIC 373 : LWLockRelease(&MyProc->fpInfoLock);
2823 :
2824 : /* Lock may have already been transferred by some other backend. */
4334 rhaas 2825 373 : if (proclock == NULL)
2826 : {
2827 : LOCK *lock;
2828 : PROCLOCKTAG proclocktag;
2829 : uint32 proclock_hashcode;
2830 :
2831 8 : LWLockAcquire(partitionLock, LW_SHARED);
2832 :
2833 8 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
2834 : locktag,
2835 : locallock->hashcode,
2836 : HASH_FIND,
2837 : NULL);
2838 8 : if (!lock)
4334 rhaas 2839 UIC 0 : elog(ERROR, "failed to re-find shared lock object");
2840 :
4334 rhaas 2841 GIC 8 : proclocktag.myLock = lock;
2842 8 : proclocktag.myProc = MyProc;
2843 :
4334 rhaas 2844 CBC 8 : proclock_hashcode = ProcLockHashCode(&proclocktag, locallock->hashcode);
2845 : proclock = (PROCLOCK *)
4334 rhaas 2846 GIC 8 : hash_search_with_hash_value(LockMethodProcLockHash,
2847 : &proclocktag,
2848 : proclock_hashcode,
2849 : HASH_FIND,
2850 : NULL);
2851 8 : if (!proclock)
4334 rhaas 2852 UIC 0 : elog(ERROR, "failed to re-find shared proclock object");
4334 rhaas 2853 GIC 8 : LWLockRelease(partitionLock);
2854 : }
6799 tgl 2855 ECB :
4334 rhaas 2856 CBC 373 : return proclock;
2857 : }
6799 tgl 2858 ECB :
6069 tgl 2859 EUB : /*
6069 tgl 2860 ECB : * GetLockConflicts
5695 2861 : * Get an array of VirtualTransactionIds of xacts currently holding locks
6069 tgl 2862 EUB : * that would conflict with the specified lock/lockmode.
2863 : * xacts merely awaiting such a lock are NOT reported.
2864 : *
2865 : * The result array is palloc'd and is terminated with an invalid VXID.
2866 : * *countp, if not null, is updated to the number of items set.
2867 : *
2868 : * Of course, the result could be out of date by the time it's returned, so
533 noah 2869 ECB : * use of this function has to be thought about carefully. Similarly, a
2870 : * PGPROC with no "lxid" will be considered non-conflicting regardless of any
2871 : * lock it holds. Existing callers don't care about a locker after that
2872 : * locker's pg_xact updates complete. CommitTransaction() clears "lxid" after
2873 : * pg_xact updates and before releasing locks.
2874 : *
5695 tgl 2875 : * Note we never include the current xact's vxid in the result array,
2876 : * since an xact never blocks itself.
2877 : */
2878 : VirtualTransactionId *
1468 alvherre 2879 CBC 1157 : GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode, int *countp)
6069 tgl 2880 ECB : {
2881 : static VirtualTransactionId *vxids;
6069 tgl 2882 GIC 1157 : LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
6069 tgl 2883 ECB : LockMethod lockMethodTable;
2884 : LOCK *lock;
2885 : LOCKMASK conflictMask;
2886 : dlist_iter proclock_iter;
2887 : PROCLOCK *proclock;
2888 : uint32 hashcode;
2889 : LWLock *partitionLock;
5695 tgl 2890 GIC 1157 : int count = 0;
4334 rhaas 2891 1157 : int fast_count = 0;
6069 tgl 2892 ECB :
6069 tgl 2893 GIC 1157 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
6069 tgl 2894 UIC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
6069 tgl 2895 CBC 1157 : lockMethodTable = LockMethods[lockmethodid];
6069 tgl 2896 GIC 1157 : if (lockmode <= 0 || lockmode > lockMethodTable->numLockModes)
6069 tgl 2897 UIC 0 : elog(ERROR, "unrecognized lock mode: %d", lockmode);
2898 :
2899 : /*
2900 : * Allocate memory to store results, and fill with InvalidVXID. We only
2901 : * need enough space for MaxBackends + max_prepared_xacts + a terminator.
2902 : * InHotStandby allocate once in TopMemoryContext.
2903 : */
4818 simon 2904 GIC 1157 : if (InHotStandby)
2905 : {
4819 2906 4 : if (vxids == NULL)
2907 1 : vxids = (VirtualTransactionId *)
4818 simon 2908 CBC 1 : MemoryContextAlloc(TopMemoryContext,
2909 : sizeof(VirtualTransactionId) *
362 rhaas 2910 1 : (MaxBackends + max_prepared_xacts + 1));
2911 : }
2912 : else
4818 simon 2913 GIC 1153 : vxids = (VirtualTransactionId *)
799 noah 2914 CBC 1153 : palloc0(sizeof(VirtualTransactionId) *
362 rhaas 2915 1153 : (MaxBackends + max_prepared_xacts + 1));
2916 :
2253 heikki.linnakangas 2917 ECB : /* Compute hash code and partition lock, and look up conflicting modes. */
6069 tgl 2918 GIC 1157 : hashcode = LockTagHashCode(locktag);
2919 1157 : partitionLock = LockHashPartitionLock(hashcode);
4334 rhaas 2920 1157 : conflictMask = lockMethodTable->conflictTab[lockmode];
2921 :
2922 : /*
2923 : * Fast path locks might not have been entered in the primary lock table.
2924 : * If the lock we're dealing with could conflict with such a lock, we must
2925 : * examine each backend's fast-path array for conflicts.
2926 : */
3966 rhaas 2927 CBC 1157 : if (ConflictsWithRelationFastPath(locktag, lockmode))
2928 : {
4334 rhaas 2929 ECB : int i;
4334 rhaas 2930 CBC 1157 : Oid relid = locktag->locktag_field2;
2931 : VirtualTransactionId vxid;
2932 :
4334 rhaas 2933 ECB : /*
2934 : * Iterate over relevant PGPROCs. Anything held by a prepared
2935 : * transaction will have been transferred to the primary lock table,
2936 : * so we need not worry about those. This is all a bit fuzzy, because
2937 : * new locks could be taken after we've visited a particular
3955 bruce 2938 : * partition, but the callers had better be prepared to deal with that
2939 : * anyway, since the locks could equally well be taken between the
4334 rhaas 2940 : * time we return the value and the time the caller does something
2941 : * with it.
2942 : */
4334 rhaas 2943 CBC 130311 : for (i = 0; i < ProcGlobal->allProcCount; i++)
2944 : {
4334 rhaas 2945 GIC 129154 : PGPROC *proc = &ProcGlobal->allProcs[i];
2946 : uint32 f;
2947 :
2948 : /* A backend never blocks itself */
4334 rhaas 2949 CBC 129154 : if (proc == MyProc)
2950 1157 : continue;
2951 :
1059 tgl 2952 GIC 127997 : LWLockAcquire(&proc->fpInfoLock, LW_SHARED);
4334 rhaas 2953 ECB :
2954 : /*
3602 bruce 2955 : * If the target backend isn't referencing the same database as
2956 : * the lock, then we needn't examine the individual relation IDs
2957 : * at all; none of them can be relevant.
2958 : *
2959 : * See FastPathTransferRelationLocks() for discussion of why we do
1363 michael 2960 : * this test after acquiring the lock.
2961 : */
3733 rhaas 2962 GIC 127997 : if (proc->databaseId != locktag->locktag_field1)
4334 rhaas 2963 ECB : {
1059 tgl 2964 GIC 54779 : LWLockRelease(&proc->fpInfoLock);
4334 rhaas 2965 54779 : continue;
2966 : }
2967 :
4334 rhaas 2968 CBC 1244429 : for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; f++)
2969 : {
2970 : uint32 lockmask;
2971 :
2972 : /* Look for an allocated slot matching the given relid. */
2973 1171440 : if (relid != proc->fpRelId[f])
4334 rhaas 2974 GIC 1170442 : continue;
4334 rhaas 2975 CBC 998 : lockmask = FAST_PATH_GET_BITS(proc, f);
4334 rhaas 2976 GIC 998 : if (!lockmask)
2977 769 : continue;
2978 229 : lockmask <<= FAST_PATH_LOCKNUMBER_OFFSET;
2979 :
4334 rhaas 2980 ECB : /*
2981 : * There can only be one entry per relation, so if we found it
2982 : * and it doesn't conflict, we can skip the rest of the slots.
2983 : */
4334 rhaas 2984 GIC 229 : if ((lockmask & conflictMask) == 0)
2985 5 : break;
4334 rhaas 2986 ECB :
2987 : /* Conflict! */
4334 rhaas 2988 CBC 224 : GET_VXID_FROM_PGPROC(vxid, *proc);
4334 rhaas 2989 ECB :
4334 rhaas 2990 GBC 224 : if (VirtualTransactionIdIsValid(vxid))
4334 rhaas 2991 CBC 224 : vxids[count++] = vxid;
2992 : /* else, xact already committed or aborted */
2993 :
2994 : /* No need to examine remaining slots. */
4334 rhaas 2995 GIC 224 : break;
2996 : }
6069 tgl 2997 ECB :
1059 tgl 2998 GIC 73218 : LWLockRelease(&proc->fpInfoLock);
4334 rhaas 2999 ECB : }
3000 : }
3001 :
3002 : /* Remember how many fast-path conflicts we found. */
4334 rhaas 3003 CBC 1157 : fast_count = count;
3004 :
3005 : /*
4334 rhaas 3006 ECB : * Look up the lock object matching the tag.
3007 : */
6069 tgl 3008 GIC 1157 : LWLockAcquire(partitionLock, LW_SHARED);
3009 :
6069 tgl 3010 CBC 1157 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
3011 : locktag,
6069 tgl 3012 ECB : hashcode,
3013 : HASH_FIND,
3014 : NULL);
6069 tgl 3015 GIC 1157 : if (!lock)
3016 : {
6069 tgl 3017 ECB : /*
6031 bruce 3018 : * If the lock object doesn't exist, there is nothing holding a lock
6031 bruce 3019 EUB : * on this lockable object.
6069 tgl 3020 ECB : */
6069 tgl 3021 CBC 70 : LWLockRelease(partitionLock);
2992 andres 3022 GIC 70 : vxids[count].backendId = InvalidBackendId;
3023 70 : vxids[count].localTransactionId = InvalidLocalTransactionId;
1468 alvherre 3024 70 : if (countp)
1468 alvherre 3025 UIC 0 : *countp = count;
5695 tgl 3026 GIC 70 : return vxids;
3027 : }
6069 tgl 3028 ECB :
3029 : /*
3030 : * Examine each existing holder (or awaiter) of the lock.
6069 tgl 3031 EUB : */
81 andres 3032 GNC 2197 : dlist_foreach(proclock_iter, &lock->procLocks)
3033 : {
3034 1110 : proclock = dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
3035 :
6069 tgl 3036 GIC 1110 : if (conflictMask & proclock->holdMask)
3037 : {
6031 bruce 3038 1106 : PGPROC *proc = proclock->tag.myProc;
3039 :
3040 : /* A backend never blocks itself */
6069 tgl 3041 1106 : if (proc != MyProc)
3042 : {
3043 : VirtualTransactionId vxid;
3044 :
5695 3045 23 : GET_VXID_FROM_PGPROC(vxid, *proc);
3046 :
3047 23 : if (VirtualTransactionIdIsValid(vxid))
4334 rhaas 3048 ECB : {
3049 : int i;
3050 :
3051 : /* Avoid duplicate entries. */
4334 rhaas 3052 GIC 43 : for (i = 0; i < fast_count; ++i)
3053 20 : if (VirtualTransactionIdEquals(vxids[i], vxid))
4334 rhaas 3054 UIC 0 : break;
4334 rhaas 3055 GIC 23 : if (i >= fast_count)
3056 23 : vxids[count++] = vxid;
3057 : }
3058 : /* else, xact already committed or aborted */
3059 : }
6069 tgl 3060 ECB : }
3061 : }
3062 :
6069 tgl 3063 GIC 1087 : LWLockRelease(partitionLock);
3064 :
362 rhaas 3065 CBC 1087 : if (count > MaxBackends + max_prepared_xacts) /* should never happen */
5695 tgl 3066 UIC 0 : elog(PANIC, "too many conflicting locks found");
3067 :
2992 andres 3068 GIC 1087 : vxids[count].backendId = InvalidBackendId;
3069 1087 : vxids[count].localTransactionId = InvalidLocalTransactionId;
1468 alvherre 3070 CBC 1087 : if (countp)
1468 alvherre 3071 GBC 1084 : *countp = count;
5695 tgl 3072 GIC 1087 : return vxids;
3073 : }
3074 :
3075 : /*
4334 rhaas 3076 ECB : * Find a lock in the shared lock table and release it. It is the caller's
3077 : * responsibility to verify that this is a sane thing to do. (For example, it
3078 : * would be bad to release a lock here if there might still be a LOCALLOCK
3079 : * object with pointers to it.)
3080 : *
3081 : * We currently use this in two situations: first, to release locks held by
3082 : * prepared transactions on commit (see lock_twophase_postcommit); and second,
3083 : * to release locks taken via the fast-path, transferred to the main hash
3084 : * table, and then released (see LockReleaseAll).
3085 : */
3086 : static void
4334 rhaas 3087 GBC 2063 : LockRefindAndRelease(LockMethod lockMethodTable, PGPROC *proc,
3088 : LOCKTAG *locktag, LOCKMODE lockmode,
3089 : bool decrement_strong_lock_count)
3090 : {
3091 : LOCK *lock;
3092 : PROCLOCK *proclock;
4334 rhaas 3093 ECB : PROCLOCKTAG proclocktag;
3094 : uint32 hashcode;
3095 : uint32 proclock_hashcode;
3359 rhaas 3096 EUB : LWLock *partitionLock;
4334 3097 : bool wakeupNeeded;
3098 :
4334 rhaas 3099 GBC 2063 : hashcode = LockTagHashCode(locktag);
4334 rhaas 3100 GIC 2063 : partitionLock = LockHashPartitionLock(hashcode);
3101 :
3102 2063 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3103 :
3104 : /*
4334 rhaas 3105 ECB : * Re-find the lock object (it had better be there).
3106 : */
4334 rhaas 3107 CBC 2063 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
3108 : locktag,
3109 : hashcode,
3110 : HASH_FIND,
4334 rhaas 3111 ECB : NULL);
4334 rhaas 3112 GIC 2063 : if (!lock)
4334 rhaas 3113 UIC 0 : elog(PANIC, "failed to re-find shared lock object");
3114 :
3115 : /*
4334 rhaas 3116 ECB : * Re-find the proclock object (ditto).
3117 : */
4334 rhaas 3118 GIC 2063 : proclocktag.myLock = lock;
4334 rhaas 3119 CBC 2063 : proclocktag.myProc = proc;
3120 :
3121 2063 : proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4334 rhaas 3122 ECB :
4334 rhaas 3123 CBC 2063 : proclock = (PROCLOCK *) hash_search_with_hash_value(LockMethodProcLockHash,
3124 : &proclocktag,
3125 : proclock_hashcode,
3126 : HASH_FIND,
3127 : NULL);
4334 rhaas 3128 GIC 2063 : if (!proclock)
4334 rhaas 3129 UIC 0 : elog(PANIC, "failed to re-find shared proclock object");
3130 :
3131 : /*
3132 : * Double-check that we are actually holding a lock of the type we want to
3133 : * release.
3134 : */
4334 rhaas 3135 GIC 2063 : if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
3136 : {
3137 : PROCLOCK_PRINT("lock_twophase_postcommit: WRONGTYPE", proclock);
4334 rhaas 3138 UIC 0 : LWLockRelease(partitionLock);
3139 0 : elog(WARNING, "you don't own a lock of type %s",
3140 : lockMethodTable->lockModeNames[lockmode]);
3141 0 : return;
3142 : }
3143 :
3144 : /*
3145 : * Do the releasing. CleanUpLock will waken any now-wakable waiters.
3146 : */
4334 rhaas 3147 GIC 2063 : wakeupNeeded = UnGrantLock(lock, lockmode, proclock, lockMethodTable);
3148 :
4334 rhaas 3149 CBC 2063 : CleanUpLock(lock, proclock,
3150 : lockMethodTable, hashcode,
3151 : wakeupNeeded);
3152 :
4334 rhaas 3153 GIC 2063 : LWLockRelease(partitionLock);
3154 :
3155 : /*
3156 : * Decrement strong lock count. This logic is needed only for 2PC.
3157 : */
3158 2063 : if (decrement_strong_lock_count
3181 3159 850 : && ConflictsWithRelationFastPath(locktag, lockmode))
3160 : {
3955 bruce 3161 64 : uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
3162 :
4282 rhaas 3163 64 : SpinLockAcquire(&FastPathStrongRelationLocks->mutex);
3289 rhaas 3164 CBC 64 : Assert(FastPathStrongRelationLocks->count[fasthashcode] > 0);
4282 3165 64 : FastPathStrongRelationLocks->count[fasthashcode]--;
3166 64 : SpinLockRelease(&FastPathStrongRelationLocks->mutex);
3167 : }
4334 rhaas 3168 ECB : }
3169 :
3170 : /*
3171 : * CheckForSessionAndXactLocks
3172 : * Check to see if transaction holds both session-level and xact-level
3173 : * locks on the same object; if so, throw an error.
624 tgl 3174 : *
3175 : * If we have both session- and transaction-level locks on the same object,
3176 : * PREPARE TRANSACTION must fail. This should never happen with regular
3177 : * locks, since we only take those at session level in some special operations
3178 : * like VACUUM. It's possible to hit this with advisory locks, though.
3179 : *
3180 : * It would be nice if we could keep the session hold and give away the
3181 : * transactional hold to the prepared xact. However, that would require two
3182 : * PROCLOCK objects, and we cannot be sure that another PROCLOCK will be
3183 : * available when it comes time for PostPrepare_Locks to do the deed.
3184 : * So for now, we error out while we can still do so safely.
3185 : *
3186 : * Since the LOCALLOCK table stores a separate entry for each lockmode,
3187 : * we can't implement this check by examining LOCALLOCK entries in isolation.
624 tgl 3188 EUB : * We must build a transient hashtable that is indexed by locktag only.
3189 : */
3190 : static void
624 tgl 3191 CBC 363 : CheckForSessionAndXactLocks(void)
624 tgl 3192 EUB : {
3193 : typedef struct
3194 : {
624 tgl 3195 ECB : LOCKTAG lock; /* identifies the lockable object */
3196 : bool sessLock; /* is any lockmode held at session level? */
3197 : bool xactLock; /* is any lockmode held at xact level? */
3198 : } PerLockTagEntry;
3199 :
3200 : HASHCTL hash_ctl;
3201 : HTAB *lockhtab;
3202 : HASH_SEQ_STATUS status;
3203 : LOCALLOCK *locallock;
3204 :
3205 : /* Create a local hash table keyed by LOCKTAG only */
624 tgl 3206 GIC 363 : hash_ctl.keysize = sizeof(LOCKTAG);
624 tgl 3207 CBC 363 : hash_ctl.entrysize = sizeof(PerLockTagEntry);
624 tgl 3208 GIC 363 : hash_ctl.hcxt = CurrentMemoryContext;
3209 :
3210 363 : lockhtab = hash_create("CheckForSessionAndXactLocks table",
3211 : 256, /* arbitrary initial size */
3212 : &hash_ctl,
3213 : HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
624 tgl 3214 ECB :
3215 : /* Scan local lock table to find entries for each LOCKTAG */
624 tgl 3216 GIC 363 : hash_seq_init(&status, LockMethodLocalHash);
3217 :
3218 1213 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3219 : {
3220 852 : LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
624 tgl 3221 ECB : PerLockTagEntry *hentry;
3222 : bool found;
3223 : int i;
3224 :
3225 : /*
3226 : * Ignore VXID locks. We don't want those to be held by prepared
3227 : * transactions, since they aren't meaningful after a restart.
3228 : */
624 tgl 3229 GIC 852 : if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
624 tgl 3230 UIC 0 : continue;
3231 :
3232 : /* Ignore it if we don't actually hold the lock */
624 tgl 3233 GIC 852 : if (locallock->nLocks <= 0)
624 tgl 3234 UIC 0 : continue;
3235 :
3236 : /* Otherwise, find or make an entry in lockhtab */
624 tgl 3237 CBC 852 : hentry = (PerLockTagEntry *) hash_search(lockhtab,
62 peter 3238 GNC 852 : &locallock->tag.lock,
3239 : HASH_ENTER, &found);
624 tgl 3240 GIC 852 : if (!found) /* initialize, if newly created */
3241 806 : hentry->sessLock = hentry->xactLock = false;
3242 :
624 tgl 3243 ECB : /* Scan to see if we hold lock at session or xact level or both */
624 tgl 3244 GIC 1704 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
3245 : {
624 tgl 3246 CBC 852 : if (lockOwners[i].owner == NULL)
624 tgl 3247 GIC 9 : hentry->sessLock = true;
624 tgl 3248 ECB : else
624 tgl 3249 GIC 843 : hentry->xactLock = true;
3250 : }
624 tgl 3251 ECB :
3252 : /*
3253 : * We can throw error immediately when we see both types of locks; no
3254 : * need to wait around to see if there are more violations.
3255 : */
624 tgl 3256 GIC 852 : if (hentry->sessLock && hentry->xactLock)
3257 2 : ereport(ERROR,
3258 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3259 : errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
624 tgl 3260 ECB : }
3261 :
3262 : /* Success, so clean up */
624 tgl 3263 GIC 361 : hash_destroy(lockhtab);
624 tgl 3264 CBC 361 : }
624 tgl 3265 EUB :
3266 : /*
3267 : * AtPrepare_Locks
6505 tgl 3268 ECB : * Do the preparatory work for a PREPARE: make 2PC state file records
3269 : * for all locks currently held.
3270 : *
3992 3271 : * Session-level locks are ignored, as are VXID locks.
6505 3272 : *
3273 : * For the most part, we don't need to touch shared memory for this ---
624 3274 : * all the necessary state information is in the locallock table.
3275 : * Fast-path locks are an exception, however: we move any such locks to
3276 : * the main table before allowing PREPARE TRANSACTION to succeed.
3277 : */
6505 3278 : void
6505 tgl 3279 CBC 363 : AtPrepare_Locks(void)
3280 : {
3281 : HASH_SEQ_STATUS status;
6505 tgl 3282 ECB : LOCALLOCK *locallock;
6505 tgl 3283 EUB :
3284 : /* First, verify there aren't locks of both xact and session level */
624 tgl 3285 GIC 363 : CheckForSessionAndXactLocks();
3286 :
3287 : /* Now do the per-locallock cleanup work */
6330 3288 361 : hash_seq_init(&status, LockMethodLocalHash);
3289 :
6505 3290 1208 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
3291 : {
3292 : TwoPhaseLockRecord record;
6505 tgl 3293 CBC 847 : LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3294 : bool haveSessionLock;
3992 tgl 3295 ECB : bool haveXactLock;
6385 bruce 3296 : int i;
3297 :
3298 : /*
3299 : * Ignore VXID locks. We don't want those to be held by prepared
3300 : * transactions, since they aren't meaningful after a restart.
3301 : */
5695 tgl 3302 GIC 847 : if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3303 7 : continue;
5695 tgl 3304 ECB :
3305 : /* Ignore it if we don't actually hold the lock */
6505 tgl 3306 GIC 847 : if (locallock->nLocks <= 0)
6505 tgl 3307 UIC 0 : continue;
3308 :
3992 tgl 3309 ECB : /* Scan to see whether we hold it at session or transaction level */
3992 tgl 3310 CBC 847 : haveSessionLock = haveXactLock = false;
6505 tgl 3311 GIC 1694 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
6505 tgl 3312 ECB : {
6505 tgl 3313 GIC 847 : if (lockOwners[i].owner == NULL)
3992 3314 7 : haveSessionLock = true;
3992 tgl 3315 ECB : else
3992 tgl 3316 GIC 840 : haveXactLock = true;
3317 : }
3318 :
3319 : /* Ignore it if we have only session lock */
3320 847 : if (!haveXactLock)
3321 7 : continue;
3322 :
3323 : /* This can't happen, because we already checked it */
3324 840 : if (haveSessionLock)
3992 tgl 3325 UIC 0 : ereport(ERROR,
3326 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3327 : errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
3328 :
3329 : /*
3330 : * If the local lock was taken via the fast-path, we need to move it
3331 : * to the primary lock table, or just get a pointer to the existing
3332 : * primary lock table entry if by chance it's already been
3955 bruce 3333 ECB : * transferred.
3334 : */
4334 rhaas 3335 CBC 840 : if (locallock->proclock == NULL)
3336 : {
4282 rhaas 3337 GIC 373 : locallock->proclock = FastPathGetRelationLockEntry(locallock);
4334 3338 373 : locallock->lock = locallock->proclock->tag.myLock;
3339 : }
3340 :
3341 : /*
3342 : * Arrange to not release any strong lock count held by this lock
3343 : * entry. We must retain the count until the prepared transaction is
3955 bruce 3344 ECB : * committed or rolled back.
3345 : */
2062 peter_e 3346 GIC 840 : locallock->holdsStrongLockCount = false;
3347 :
6505 tgl 3348 ECB : /*
3349 : * Create a 2PC record.
3350 : */
6505 tgl 3351 GIC 840 : memcpy(&(record.locktag), &(locallock->tag.lock), sizeof(LOCKTAG));
3352 840 : record.lockmode = locallock->tag.mode;
3353 :
3354 840 : RegisterTwoPhaseRecord(TWOPHASE_RM_LOCK_ID, 0,
3355 : &record, sizeof(TwoPhaseLockRecord));
3356 : }
3357 361 : }
3358 :
6505 tgl 3359 ECB : /*
3360 : * PostPrepare_Locks
3361 : * Clean up after successful PREPARE
3362 : *
3363 : * Here, we want to transfer ownership of our locks to a dummy PGPROC
3364 : * that's now associated with the prepared transaction, and we want to
3365 : * clean out the corresponding entries in the LOCALLOCK table.
3366 : *
3367 : * Note: by removing the LOCALLOCK entries, we are leaving dangling
3368 : * pointers in the transaction's resource owner. This is OK at the
3369 : * moment since resowner.c doesn't try to free locks retail at a toplevel
3370 : * transaction commit or abort. We could alternatively zero out nLocks
3371 : * and leave the LOCALLOCK entries to be garbage-collected by LockReleaseAll,
3372 : * but that probably costs more cycles.
3373 : */
6505 tgl 3374 EUB : void
6505 tgl 3375 GBC 361 : PostPrepare_Locks(TransactionId xid)
6505 tgl 3376 EUB : {
1504 michael 3377 GIC 361 : PGPROC *newproc = TwoPhaseGetDummyProc(xid, false);
3378 : HASH_SEQ_STATUS status;
3379 : LOCALLOCK *locallock;
6328 tgl 3380 ECB : LOCK *lock;
6505 tgl 3381 EUB : PROCLOCK *proclock;
3382 : PROCLOCKTAG proclocktag;
3383 : int partition;
6505 tgl 3384 ECB :
2618 rhaas 3385 : /* Can't prepare a lock group follower. */
2618 rhaas 3386 GIC 361 : Assert(MyProc->lockGroupLeader == NULL ||
2618 rhaas 3387 ECB : MyProc->lockGroupLeader == MyProc);
3388 :
3389 : /* This is a critical section: any error means big trouble */
6505 tgl 3390 CBC 361 : START_CRIT_SECTION();
3391 :
3392 : /*
3393 : * First we run through the locallock table and get rid of unwanted
6385 bruce 3394 ECB : * entries, then we scan the process's proclocks and transfer them to the
3395 : * target proc.
3396 : *
3397 : * We do this separately because we may have multiple locallock entries
3398 : * pointing to the same proclock, and we daren't end up with any dangling
6385 bruce 3399 EUB : * pointers.
3400 : */
6330 tgl 3401 GIC 361 : hash_seq_init(&status, LockMethodLocalHash);
3402 :
6505 3403 1208 : while ((locallock = (LOCALLOCK *) hash_seq_search(&status)) != NULL)
6505 tgl 3404 ECB : {
3992 tgl 3405 CBC 847 : LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
3406 : bool haveSessionLock;
3407 : bool haveXactLock;
3992 tgl 3408 ECB : int i;
3409 :
6505 tgl 3410 GIC 847 : if (locallock->proclock == NULL || locallock->lock == NULL)
3411 : {
3412 : /*
3413 : * We must've run out of shared memory while trying to set up this
6385 bruce 3414 ECB : * lock. Just forget the local entry.
3415 : */
6505 tgl 3416 UIC 0 : Assert(locallock->nLocks == 0);
6505 tgl 3417 LBC 0 : RemoveLocalLock(locallock);
6505 tgl 3418 UIC 0 : continue;
3419 : }
6505 tgl 3420 ECB :
3421 : /* Ignore VXID locks */
5695 tgl 3422 GIC 847 : if (locallock->tag.lock.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
5695 tgl 3423 UIC 0 : continue;
3424 :
3425 : /* Scan to see whether we hold it at session or transaction level */
3992 tgl 3426 GIC 847 : haveSessionLock = haveXactLock = false;
3427 1694 : for (i = locallock->numLockOwners - 1; i >= 0; i--)
3428 : {
3429 847 : if (lockOwners[i].owner == NULL)
3992 tgl 3430 CBC 7 : haveSessionLock = true;
3992 tgl 3431 ECB : else
3992 tgl 3432 GIC 840 : haveXactLock = true;
3992 tgl 3433 ECB : }
3434 :
3435 : /* Ignore it if we have only session lock */
3992 tgl 3436 GIC 847 : if (!haveXactLock)
3992 tgl 3437 CBC 7 : continue;
3438 :
3992 tgl 3439 ECB : /* This can't happen, because we already checked it */
3992 tgl 3440 GIC 840 : if (haveSessionLock)
3992 tgl 3441 LBC 0 : ereport(PANIC,
3442 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3443 : errmsg("cannot PREPARE while holding both session-level and transaction-level locks on the same object")));
6505 tgl 3444 ECB :
3445 : /* Mark the proclock to show we need to release this lockmode */
6505 tgl 3446 GIC 840 : if (locallock->nLocks > 0)
3447 840 : locallock->proclock->releaseMask |= LOCKBIT_ON(locallock->tag.mode);
3448 :
6505 tgl 3449 ECB : /* And remove the locallock hashtable entry */
6505 tgl 3450 CBC 840 : RemoveLocalLock(locallock);
6505 tgl 3451 ECB : }
3452 :
3453 : /*
3454 : * Now, scan each lock partition separately.
6328 3455 : */
6328 tgl 3456 CBC 6137 : for (partition = 0; partition < NUM_LOCK_PARTITIONS; partition++)
3457 : {
3458 : LWLock *partitionLock;
81 andres 3459 GNC 5776 : dlist_head *procLocks = &(MyProc->myProcLocks[partition]);
3460 : dlist_mutable_iter proclock_iter;
3461 :
3359 rhaas 3462 GIC 5776 : partitionLock = LockHashPartitionLockByIndex(partition);
3463 :
3464 : /*
3465 : * If the proclock list for this partition is empty, we can skip
3466 : * acquiring the partition lock. This optimization is safer than the
3467 : * situation in LockReleaseAll, because we got rid of any fast-path
3468 : * locks during AtPrepare_Locks, so there cannot be any case where
3469 : * another backend is adding something to our lists now. For safety,
3470 : * though, we code this the same way as in LockReleaseAll.
3471 : */
81 andres 3472 GNC 5776 : if (dlist_is_empty(procLocks))
6328 tgl 3473 GIC 4976 : continue; /* needn't examine this partition */
6505 tgl 3474 ECB :
6328 tgl 3475 GIC 800 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
3476 :
81 andres 3477 GNC 1638 : dlist_foreach_modify(proclock_iter, procLocks)
3478 : {
3479 838 : proclock = dlist_container(PROCLOCK, procLink, proclock_iter.cur);
6505 tgl 3480 ECB :
6104 tgl 3481 CBC 838 : Assert(proclock->tag.myProc == MyProc);
3482 :
6104 tgl 3483 GIC 838 : lock = proclock->tag.myLock;
3484 :
3485 : /* Ignore VXID locks */
5695 3486 838 : if (lock->tag.locktag_type == LOCKTAG_VIRTUALTRANSACTION)
3419 3487 35 : continue;
5695 tgl 3488 ECB :
3489 : PROCLOCK_PRINT("PostPrepare_Locks", proclock);
3490 : LOCK_PRINT("PostPrepare_Locks", lock, 0);
6328 tgl 3491 GBC 803 : Assert(lock->nRequested >= 0);
6328 tgl 3492 GIC 803 : Assert(lock->nGranted >= 0);
3493 803 : Assert(lock->nGranted <= lock->nRequested);
6328 tgl 3494 CBC 803 : Assert((proclock->holdMask & ~lock->grantMask) == 0);
3495 :
3496 : /* Ignore it if nothing to release (must be a session lock) */
3992 tgl 3497 GIC 803 : if (proclock->releaseMask == 0)
3419 3498 7 : continue;
3992 tgl 3499 ECB :
3500 : /* Else we should be releasing all locks */
6328 tgl 3501 GIC 796 : if (proclock->releaseMask != proclock->holdMask)
6328 tgl 3502 LBC 0 : elog(PANIC, "we seem to have dropped a bit somewhere");
6505 tgl 3503 ECB :
3504 : /*
3505 : * We cannot simply modify proclock->tag.myProc to reassign
3506 : * ownership of the lock, because that's part of the hash key and
3507 : * the proclock would then be in the wrong hash chain. Instead
3508 : * use hash_update_hash_key. (We used to create a new hash entry,
3509 : * but that risks out-of-memory failure if other processes are
3602 bruce 3510 : * busy making proclocks too.) We must unlink the proclock from
3511 : * our procLink chain and put it into the new proc's chain, too.
3738 tgl 3512 : *
3513 : * Note: the updated proclock hash key will still belong to the
3514 : * same hash partition, cf proclock_hash(). So the partition lock
3515 : * we already hold is sufficient for this.
6328 3516 : */
81 andres 3517 GNC 796 : dlist_delete(&proclock->procLink);
3518 :
3519 : /*
3738 tgl 3520 ECB : * Create the new hash key for the proclock.
6328 3521 : */
6104 tgl 3522 GIC 796 : proclocktag.myLock = lock;
3523 796 : proclocktag.myProc = newproc;
3524 :
3525 : /*
2618 rhaas 3526 ECB : * Update groupLeader pointer to point to the new proc. (We'd
3527 : * better not be a member of somebody else's lock group!)
3528 : */
2618 rhaas 3529 GIC 796 : Assert(proclock->groupLeader == proclock->tag.myProc);
3530 796 : proclock->groupLeader = newproc;
3531 :
3532 : /*
3533 : * Update the proclock. We should not find any existing entry for
3534 : * the same hash key, since there can be only one entry for any
3535 : * given lock with my own proc.
3536 : */
3738 tgl 3537 796 : if (!hash_update_hash_key(LockMethodProcLockHash,
3538 : proclock,
3539 : &proclocktag))
3738 tgl 3540 UIC 0 : elog(PANIC, "duplicate entry found while reassigning a prepared transaction's locks");
3541 :
3542 : /* Re-link into the new proc's proclock list */
81 andres 3543 GNC 796 : dlist_push_tail(&newproc->myProcLocks[partition], &proclock->procLink);
3544 :
3545 : PROCLOCK_PRINT("PostPrepare_Locks: updated", proclock);
6031 bruce 3546 ECB : } /* loop over PROCLOCKs within this partition */
3547 :
6328 tgl 3548 GIC 800 : LWLockRelease(partitionLock);
3549 : } /* loop over partitions */
3550 :
6505 3551 361 : END_CRIT_SECTION();
3552 361 : }
3553 :
3554 :
6766 tgl 3555 ECB : /*
3556 : * Estimate shared-memory space used for lock tables
3557 : */
6441 3558 : Size
6505 tgl 3559 CBC 2738 : LockShmemSize(void)
9770 scrappy 3560 ECB : {
6330 tgl 3561 GIC 2738 : Size size = 0;
3562 : long max_table_size;
3563 :
3564 : /* lock hash table */
6328 3565 2738 : max_table_size = NLOCKENTS();
6104 3566 2738 : size = add_size(size, hash_estimate_size(max_table_size, sizeof(LOCK)));
3567 :
3568 : /* proclock hash table */
6328 3569 2738 : max_table_size *= 2;
6104 3570 2738 : size = add_size(size, hash_estimate_size(max_table_size, sizeof(PROCLOCK)));
3571 :
3572 : /*
3573 : * Since NLOCKENTS is only an estimate, add 10% safety margin.
8800 tgl 3574 ECB : */
6441 tgl 3575 GIC 2738 : size = add_size(size, size / 10);
9345 bruce 3576 ECB :
9345 bruce 3577 GIC 2738 : return size;
3578 : }
9770 scrappy 3579 ECB :
3580 : /*
7540 bruce 3581 : * GetLockStatusData - Return a summary of the lock manager's internal
3582 : * status, for use in a user-level reporting function.
3583 : *
2612 tgl 3584 : * The return data consists of an array of LockInstanceData objects,
3585 : * which are a lightly abstracted version of the PROCLOCK data structures,
3586 : * i.e. there is one entry for each unique lock and interested PGPROC.
3587 : * It is the caller's responsibility to match up related items (such as
3588 : * references to the same lockable object or PGPROC) if wanted.
3589 : *
6328 3590 : * The design goal is to hold the LWLocks for as short a time as possible;
3591 : * thus, this function simply makes a copy of the necessary data and releases
3592 : * the locks, allowing the caller to contemplate and format the data for as
7526 3593 : * long as it pleases.
7540 bruce 3594 : */
3595 : LockData *
7526 tgl 3596 GIC 264 : GetLockStatusData(void)
7540 bruce 3597 ECB : {
7522 3598 : LockData *data;
3599 : PROCLOCK *proclock;
7540 3600 : HASH_SEQ_STATUS seqstat;
6328 tgl 3601 : int els;
3602 : int el;
7522 bruce 3603 : int i;
7540 3604 :
7526 tgl 3605 CBC 264 : data = (LockData *) palloc(sizeof(LockData));
7540 bruce 3606 ECB :
3607 : /* Guess how much space we'll need. */
362 rhaas 3608 GIC 264 : els = MaxBackends;
4334 3609 264 : el = 0;
3610 264 : data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * els);
3611 :
4334 rhaas 3612 ECB : /*
3613 : * First, we iterate through the per-backend fast-path arrays, locking
3260 bruce 3614 : * them one at a time. This might produce an inconsistent picture of the
3615 : * system state, but taking all of those LWLocks at the same time seems
3616 : * impractical (in particular, note MAX_SIMUL_LWLOCKS). It shouldn't
4334 rhaas 3617 : * matter too much, because none of these locks can be involved in lock
3618 : * conflicts anyway - anything that might must be present in the main lock
3619 : * table. (For the same reason, we don't sweat about making leaderPid
3620 : * completely valid. We cannot safely dereference another backend's
3621 : * lockGroupLeader field without holding all lock partition locks, and
2603 tgl 3622 : * it's not worth that.)
3623 : */
4334 rhaas 3624 CBC 27652 : for (i = 0; i < ProcGlobal->allProcCount; ++i)
4334 rhaas 3625 ECB : {
4334 rhaas 3626 CBC 27388 : PGPROC *proc = &ProcGlobal->allProcs[i];
3627 : uint32 f;
3628 :
1059 tgl 3629 27388 : LWLockAcquire(&proc->fpInfoLock, LW_SHARED);
4334 rhaas 3630 ECB :
4334 rhaas 3631 GIC 465596 : for (f = 0; f < FP_LOCK_SLOTS_PER_BACKEND; ++f)
4334 rhaas 3632 ECB : {
3955 bruce 3633 : LockInstanceData *instance;
4334 rhaas 3634 CBC 438208 : uint32 lockbits = FAST_PATH_GET_BITS(proc, f);
4334 rhaas 3635 ECB :
3636 : /* Skip unallocated slots. */
4334 rhaas 3637 CBC 438208 : if (!lockbits)
3638 434298 : continue;
4334 rhaas 3639 ECB :
4334 rhaas 3640 CBC 3910 : if (el >= els)
4334 rhaas 3641 ECB : {
362 rhaas 3642 GIC 15 : els += MaxBackends;
4334 rhaas 3643 CBC 15 : data->locks = (LockInstanceData *)
4334 rhaas 3644 GIC 15 : repalloc(data->locks, sizeof(LockInstanceData) * els);
3645 : }
4334 rhaas 3646 ECB :
4282 rhaas 3647 GIC 3910 : instance = &data->locks[el];
4334 3648 3910 : SET_LOCKTAG_RELATION(instance->locktag, proc->databaseId,
3649 : proc->fpRelId[f]);
3650 3910 : instance->holdMask = lockbits << FAST_PATH_LOCKNUMBER_OFFSET;
3651 3910 : instance->waitLockMode = NoLock;
3652 3910 : instance->backend = proc->backendId;
3653 3910 : instance->lxid = proc->lxid;
3654 3910 : instance->pid = proc->pid;
2603 tgl 3655 3910 : instance->leaderPid = proc->pid;
4334 rhaas 3656 3910 : instance->fastpath = true;
3657 :
3658 : /*
3659 : * Successfully taking fast path lock means there were no
3660 : * conflicting locks.
3661 : */
783 fujii 3662 CBC 3910 : instance->waitStart = 0;
783 fujii 3663 ECB :
4334 rhaas 3664 GIC 3910 : el++;
3665 : }
4334 rhaas 3666 ECB :
4266 rhaas 3667 CBC 27388 : if (proc->fpVXIDLock)
3668 : {
3955 bruce 3669 ECB : VirtualTransactionId vxid;
3670 : LockInstanceData *instance;
4266 rhaas 3671 :
4266 rhaas 3672 GIC 1250 : if (el >= els)
3673 : {
362 3674 3 : els += MaxBackends;
4266 rhaas 3675 CBC 3 : data->locks = (LockInstanceData *)
4266 rhaas 3676 GIC 3 : repalloc(data->locks, sizeof(LockInstanceData) * els);
4266 rhaas 3677 ECB : }
3678 :
4266 rhaas 3679 CBC 1250 : vxid.backendId = proc->backendId;
3680 1250 : vxid.localTransactionId = proc->fpLocalTransactionId;
4266 rhaas 3681 ECB :
4266 rhaas 3682 GIC 1250 : instance = &data->locks[el];
4266 rhaas 3683 CBC 1250 : SET_LOCKTAG_VIRTUALTRANSACTION(instance->locktag, vxid);
3684 1250 : instance->holdMask = LOCKBIT_ON(ExclusiveLock);
3685 1250 : instance->waitLockMode = NoLock;
3686 1250 : instance->backend = proc->backendId;
4266 rhaas 3687 GIC 1250 : instance->lxid = proc->lxid;
4266 rhaas 3688 CBC 1250 : instance->pid = proc->pid;
2603 tgl 3689 1250 : instance->leaderPid = proc->pid;
4266 rhaas 3690 1250 : instance->fastpath = true;
783 fujii 3691 1250 : instance->waitStart = 0;
4266 rhaas 3692 ECB :
4266 rhaas 3693 CBC 1250 : el++;
4266 rhaas 3694 ECB : }
3695 :
1059 tgl 3696 CBC 27388 : LWLockRelease(&proc->fpInfoLock);
3697 : }
3698 :
3699 : /*
3700 : * Next, acquire lock on the entire shared lock data structure. We do
3701 : * this so that, at least for locks in the primary lock table, the state
3702 : * will be self-consistent.
3703 : *
3704 : * Since this is a read-only operation, we take shared instead of
3705 : * exclusive lock. There's not a whole lot of point to this, because all
6031 bruce 3706 ECB : * the normal operations require exclusive lock, but it doesn't hurt
3707 : * anything either. It will at least allow two backends to do
3708 : * GetLockStatusData in parallel.
6328 tgl 3709 : *
3710 : * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3711 : */
6328 tgl 3712 GIC 4488 : for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3359 rhaas 3713 4224 : LWLockAcquire(LockHashPartitionLockByIndex(i), LW_SHARED);
3714 :
3715 : /* Now we can safely count the number of proclocks */
4334 3716 264 : data->nelements = el + hash_get_num_entries(LockMethodProcLockHash);
3717 264 : if (data->nelements > els)
3718 : {
3719 13 : els = data->nelements;
3720 13 : data->locks = (LockInstanceData *)
3721 13 : repalloc(data->locks, sizeof(LockInstanceData) * els);
3722 : }
3723 :
3724 : /* Now scan the tables to copy the data */
6104 tgl 3725 264 : hash_seq_init(&seqstat, LockMethodProcLockHash);
3726 :
3727 2964 : while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
3728 : {
3729 2700 : PGPROC *proc = proclock->tag.myProc;
3730 2700 : LOCK *lock = proclock->tag.myLock;
3955 bruce 3731 2700 : LockInstanceData *instance = &data->locks[el];
3732 :
4334 rhaas 3733 2700 : memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
3734 2700 : instance->holdMask = proclock->holdMask;
3735 2700 : if (proc->waitLock == proclock->tag.myLock)
3736 8 : instance->waitLockMode = proc->waitLockMode;
3737 : else
4334 rhaas 3738 CBC 2692 : instance->waitLockMode = NoLock;
4334 rhaas 3739 GIC 2700 : instance->backend = proc->backendId;
3740 2700 : instance->lxid = proc->lxid;
3741 2700 : instance->pid = proc->pid;
2603 tgl 3742 2700 : instance->leaderPid = proclock->groupLeader->pid;
4334 rhaas 3743 2700 : instance->fastpath = false;
783 fujii 3744 CBC 2700 : instance->waitStart = (TimestampTz) pg_atomic_read_u64(&proc->waitStart);
3745 :
6104 tgl 3746 GIC 2700 : el++;
3747 : }
3748 :
3749 : /*
3750 : * And release locks. We do this in reverse order for two reasons: (1)
3751 : * Anyone else who needs more than one of the locks will be trying to lock
5624 bruce 3752 ECB : * them in increasing order; we don't want to release the other process
3753 : * until it can get all the locks it needs. (2) This avoids O(N^2)
3754 : * behavior inside LWLockRelease.
5746 tgl 3755 : */
6031 bruce 3756 CBC 4488 : for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3359 rhaas 3757 GIC 4224 : LWLockRelease(LockHashPartitionLockByIndex(i));
3758 :
6328 tgl 3759 264 : Assert(el == data->nelements);
3760 :
7526 3761 264 : return data;
3762 : }
3763 :
3764 : /*
3765 : * GetBlockerStatusData - Return a summary of the lock manager's state
3766 : * concerning locks that are blocking the specified PID or any member of
3767 : * the PID's lock group, for use in a user-level reporting function.
3768 : *
2603 tgl 3769 ECB : * For each PID within the lock group that is awaiting some heavyweight lock,
3770 : * the return data includes an array of LockInstanceData objects, which are
3771 : * the same data structure used by GetLockStatusData; but unlike that function,
3772 : * this one reports only the PROCLOCKs associated with the lock that that PID
3773 : * is blocked on. (Hence, all the locktags should be the same for any one
3774 : * blocked PID.) In addition, we return an array of the PIDs of those backends
3775 : * that are ahead of the blocked PID in the lock's wait queue. These can be
3776 : * compared with the PIDs in the LockInstanceData objects to determine which
3777 : * waiters are ahead of or behind the blocked PID in the queue.
3778 : *
3779 : * If blocked_pid isn't a valid backend PID or nothing in its lock group is
3780 : * waiting on any heavyweight lock, return empty arrays.
3781 : *
3782 : * The design goal is to hold the LWLocks for as short a time as possible;
3783 : * thus, this function simply makes a copy of the necessary data and releases
3784 : * the locks, allowing the caller to contemplate and format the data for as
3785 : * long as it pleases.
3786 : */
3787 : BlockedProcsData *
2603 tgl 3788 GIC 3192 : GetBlockerStatusData(int blocked_pid)
3789 : {
3790 : BlockedProcsData *data;
3791 : PGPROC *proc;
3792 : int i;
2603 tgl 3793 ECB :
2603 tgl 3794 GIC 3192 : data = (BlockedProcsData *) palloc(sizeof(BlockedProcsData));
3795 :
3796 : /*
2603 tgl 3797 ECB : * Guess how much space we'll need, and preallocate. Most of the time
3798 : * this will avoid needing to do repalloc while holding the LWLocks. (We
3799 : * assume, but check with an Assert, that MaxBackends is enough entries
3800 : * for the procs[] array; the other two could need enlargement, though.)
3801 : */
2603 tgl 3802 GIC 3192 : data->nprocs = data->nlocks = data->npids = 0;
362 rhaas 3803 3192 : data->maxprocs = data->maxlocks = data->maxpids = MaxBackends;
2603 tgl 3804 3192 : data->procs = (BlockedProcData *) palloc(sizeof(BlockedProcData) * data->maxprocs);
2603 tgl 3805 CBC 3192 : data->locks = (LockInstanceData *) palloc(sizeof(LockInstanceData) * data->maxlocks);
3806 3192 : data->waiter_pids = (int *) palloc(sizeof(int) * data->maxpids);
3807 :
2603 tgl 3808 ECB : /*
3809 : * In order to search the ProcArray for blocked_pid and assume that that
3810 : * entry won't immediately disappear under us, we must hold ProcArrayLock.
3811 : * In addition, to examine the lock grouping fields of any other backend,
3812 : * we must hold all the hash partition locks. (Only one of those locks is
3813 : * actually relevant for any one lock group, but we can't know which one
3814 : * ahead of time.) It's fairly annoying to hold all those locks
3815 : * throughout this, but it's no worse than GetLockStatusData(), and it
3816 : * does have the advantage that we're guaranteed to return a
3817 : * self-consistent instantaneous state.
3818 : */
2603 tgl 3819 GIC 3192 : LWLockAcquire(ProcArrayLock, LW_SHARED);
2603 tgl 3820 ECB :
2603 tgl 3821 GIC 3192 : proc = BackendPidGetProcWithLock(blocked_pid);
3822 :
3823 : /* Nothing to do if it's gone */
3824 3192 : if (proc != NULL)
3825 : {
3826 : /*
3827 : * Acquire lock on the entire shared lock data structure. See notes
2603 tgl 3828 ECB : * in GetLockStatusData().
3829 : */
2603 tgl 3830 GIC 54264 : for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3831 51072 : LWLockAcquire(LockHashPartitionLockByIndex(i), LW_SHARED);
2603 tgl 3832 ECB :
2603 tgl 3833 CBC 3192 : if (proc->lockGroupLeader == NULL)
2603 tgl 3834 ECB : {
3835 : /* Easy case, proc is not a lock group member */
2603 tgl 3836 GIC 3035 : GetSingleProcBlockerStatusData(proc, data);
3837 : }
3838 : else
3839 : {
3840 : /* Examine all procs in proc's lock group */
3841 : dlist_iter iter;
3842 :
2603 tgl 3843 CBC 404 : dlist_foreach(iter, &proc->lockGroupLeader->lockGroupMembers)
3844 : {
2603 tgl 3845 ECB : PGPROC *memberProc;
3846 :
2603 tgl 3847 CBC 247 : memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
3848 247 : GetSingleProcBlockerStatusData(memberProc, data);
3849 : }
3850 : }
2603 tgl 3851 ECB :
3852 : /*
2603 tgl 3853 EUB : * And release locks. See notes in GetLockStatusData().
3854 : */
2603 tgl 3855 GBC 54264 : for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
2603 tgl 3856 GIC 51072 : LWLockRelease(LockHashPartitionLockByIndex(i));
3857 :
2603 tgl 3858 CBC 3192 : Assert(data->nprocs <= data->maxprocs);
2603 tgl 3859 ECB : }
3860 :
2603 tgl 3861 CBC 3192 : LWLockRelease(ProcArrayLock);
2603 tgl 3862 ECB :
2603 tgl 3863 GIC 3192 : return data;
2603 tgl 3864 ECB : }
3865 :
3866 : /* Accumulate data about one possibly-blocked proc for GetBlockerStatusData */
3867 : static void
2603 tgl 3868 CBC 3282 : GetSingleProcBlockerStatusData(PGPROC *blocked_proc, BlockedProcsData *data)
2603 tgl 3869 ECB : {
2603 tgl 3870 CBC 3282 : LOCK *theLock = blocked_proc->waitLock;
3871 : BlockedProcData *bproc;
3872 : dlist_iter proclock_iter;
3873 : dlist_iter proc_iter;
3874 : dclist_head *waitQueue;
3875 : int queue_size;
3876 :
2603 tgl 3877 EUB : /* Nothing to do if this proc is not blocked */
2603 tgl 3878 GIC 3282 : if (theLock == NULL)
2603 tgl 3879 GBC 2193 : return;
2603 tgl 3880 EUB :
3881 : /* Set up a procs[] element */
2603 tgl 3882 GIC 1089 : bproc = &data->procs[data->nprocs++];
3883 1089 : bproc->pid = blocked_proc->pid;
2603 tgl 3884 CBC 1089 : bproc->first_lock = data->nlocks;
2603 tgl 3885 GIC 1089 : bproc->first_waiter = data->npids;
2603 tgl 3886 ECB :
3887 : /*
3888 : * We may ignore the proc's fast-path arrays, since nothing in those could
3889 : * be related to a contended lock.
3890 : */
3891 :
3892 : /* Collect all PROCLOCKs associated with theLock */
81 andres 3893 GNC 3312 : dlist_foreach(proclock_iter, &theLock->procLocks)
3894 : {
3895 2223 : PROCLOCK *proclock =
3896 2223 : dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
2603 tgl 3897 GIC 2223 : PGPROC *proc = proclock->tag.myProc;
3898 2223 : LOCK *lock = proclock->tag.myLock;
3899 : LockInstanceData *instance;
3900 :
3901 2223 : if (data->nlocks >= data->maxlocks)
3902 : {
362 rhaas 3903 UIC 0 : data->maxlocks += MaxBackends;
2603 tgl 3904 0 : data->locks = (LockInstanceData *)
3905 0 : repalloc(data->locks, sizeof(LockInstanceData) * data->maxlocks);
3906 : }
3907 :
2603 tgl 3908 GIC 2223 : instance = &data->locks[data->nlocks];
2603 tgl 3909 CBC 2223 : memcpy(&instance->locktag, &lock->tag, sizeof(LOCKTAG));
2603 tgl 3910 GIC 2223 : instance->holdMask = proclock->holdMask;
3911 2223 : if (proc->waitLock == lock)
3912 1126 : instance->waitLockMode = proc->waitLockMode;
3913 : else
3914 1097 : instance->waitLockMode = NoLock;
3915 2223 : instance->backend = proc->backendId;
3916 2223 : instance->lxid = proc->lxid;
3917 2223 : instance->pid = proc->pid;
3918 2223 : instance->leaderPid = proclock->groupLeader->pid;
3919 2223 : instance->fastpath = false;
3920 2223 : data->nlocks++;
2603 tgl 3921 ECB : }
3922 :
3923 : /* Enlarge waiter_pids[] if it's too small to hold all wait queue PIDs */
2603 tgl 3924 CBC 1089 : waitQueue = &(theLock->waitProcs);
81 andres 3925 GNC 1089 : queue_size = dclist_count(waitQueue);
3926 :
2603 tgl 3927 GIC 1089 : if (queue_size > data->maxpids - data->npids)
3928 : {
362 rhaas 3929 UIC 0 : data->maxpids = Max(data->maxpids + MaxBackends,
2603 tgl 3930 ECB : data->npids + queue_size);
2603 tgl 3931 UIC 0 : data->waiter_pids = (int *) repalloc(data->waiter_pids,
3932 0 : sizeof(int) * data->maxpids);
2603 tgl 3933 ECB : }
3934 :
3935 : /* Collect PIDs from the lock's wait queue, stopping at blocked_proc */
81 andres 3936 GNC 1107 : dclist_foreach(proc_iter, waitQueue)
3937 : {
3938 1107 : PGPROC *queued_proc = dlist_container(PGPROC, links, proc_iter.cur);
186 drowley 3939 1107 : if (queued_proc == blocked_proc)
2603 tgl 3940 GIC 1089 : break;
186 drowley 3941 GNC 18 : data->waiter_pids[data->npids++] = queued_proc->pid;
3942 18 : queued_proc = (PGPROC *) queued_proc->links.next;
2603 tgl 3943 ECB : }
3944 :
2603 tgl 3945 GIC 1089 : bproc->num_locks = data->nlocks - bproc->first_lock;
2603 tgl 3946 CBC 1089 : bproc->num_waiters = data->npids - bproc->first_waiter;
2603 tgl 3947 ECB : }
3948 :
4859 simon 3949 : /*
3596 tgl 3950 : * Returns a list of currently held AccessExclusiveLocks, for use by
3951 : * LogStandbySnapshot(). The result is a palloc'd array,
3952 : * with the number of elements returned into *nlocks.
3953 : *
3954 : * XXX This currently takes a lock on all partitions of the lock table,
3955 : * but it's possible to do better. By reference counting locks and storing
3956 : * the value in the ProcArray entry for each backend we could tell if any
3957 : * locks need recording without having to acquire the partition locks and
3958 : * scan the lock table. Whether that's worth the additional overhead
3959 : * is pretty dubious though.
4859 simon 3960 : */
3961 : xl_standby_lock *
4859 simon 3962 CBC 1749 : GetRunningTransactionLocks(int *nlocks)
4859 simon 3963 ECB : {
3596 tgl 3964 : xl_standby_lock *accessExclusiveLocks;
3965 : PROCLOCK *proclock;
4859 simon 3966 : HASH_SEQ_STATUS seqstat;
3967 : int i;
3968 : int index;
3969 : int els;
3970 :
3971 : /*
3972 : * Acquire lock on the entire shared lock data structure.
3973 : *
3974 : * Must grab LWLocks in partition-number order to avoid LWLock deadlock.
3975 : */
4859 simon 3976 GIC 29733 : for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
3359 rhaas 3977 27984 : LWLockAcquire(LockHashPartitionLockByIndex(i), LW_SHARED);
3978 :
4859 simon 3979 ECB : /* Now we can safely count the number of proclocks */
4859 simon 3980 CBC 1749 : els = hash_get_num_entries(LockMethodProcLockHash);
3981 :
4859 simon 3982 ECB : /*
3983 : * Allocating enough space for all locks in the lock table is overkill,
3984 : * but it's more convenient and faster than having to enlarge the array.
3985 : */
4859 simon 3986 GIC 1749 : accessExclusiveLocks = palloc(els * sizeof(xl_standby_lock));
3987 :
3743 tgl 3988 ECB : /* Now scan the tables to copy the data */
3743 tgl 3989 GIC 1749 : hash_seq_init(&seqstat, LockMethodProcLockHash);
3743 tgl 3990 ECB :
4859 simon 3991 : /*
4790 bruce 3992 : * If lock is a currently granted AccessExclusiveLock then it will have
3993 : * just one proclock holder, so locks are never accessed twice in this
3994 : * particular case. Don't copy this code for use elsewhere because in the
3995 : * general case this will give you duplicate locks when looking at
3996 : * non-exclusive lock types.
3997 : */
4859 simon 3998 GIC 1749 : index = 0;
3999 5840 : while ((proclock = (PROCLOCK *) hash_seq_search(&seqstat)))
4000 : {
4001 : /* make sure this definition matches the one used in LockAcquire */
4002 4091 : if ((proclock->holdMask & LOCKBIT_ON(AccessExclusiveLock)) &&
4003 160 : proclock->tag.myLock->tag.locktag_type == LOCKTAG_RELATION)
4004 : {
4790 bruce 4005 115 : PGPROC *proc = proclock->tag.myProc;
4006 115 : LOCK *lock = proclock->tag.myLock;
968 andres 4007 115 : TransactionId xid = proc->xid;
4008 :
4009 : /*
4010 : * Don't record locks for transactions if we know they have
4011 : * already issued their WAL record for commit but not yet released
4012 : * lock. It is still possible that we see locks held by already
4013 : * complete transactions, if they haven't yet zeroed their xids.
4014 : */
4094 simon 4015 115 : if (!TransactionIdIsValid(xid))
4016 1 : continue;
4017 :
4018 114 : accessExclusiveLocks[index].xid = xid;
4790 bruce 4019 114 : accessExclusiveLocks[index].dbOid = lock->tag.locktag_field1;
4859 simon 4020 114 : accessExclusiveLocks[index].relOid = lock->tag.locktag_field2;
4021 :
4022 114 : index++;
4023 : }
4024 : }
4025 :
3596 tgl 4026 1749 : Assert(index <= els);
4027 :
4028 : /*
4029 : * And release locks. We do this in reverse order for two reasons: (1)
4030 : * Anyone else who needs more than one of the locks will be trying to lock
4031 : * them in increasing order; we don't want to release the other process
4032 : * until it can get all the locks it needs. (2) This avoids O(N^2)
4033 : * behavior inside LWLockRelease.
4034 : */
4859 simon 4035 29733 : for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
3359 rhaas 4036 27984 : LWLockRelease(LockHashPartitionLockByIndex(i));
4037 :
4859 simon 4038 1749 : *nlocks = index;
4039 1749 : return accessExclusiveLocks;
4040 : }
4041 :
4042 : /* Provide the textual name of any lock mode */
4043 : const char *
6330 tgl 4044 8169 : GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
4045 : {
4046 8169 : Assert(lockmethodid > 0 && lockmethodid < lengthof(LockMethods));
4047 8169 : Assert(mode > 0 && mode <= LockMethods[lockmethodid]->numLockModes);
4048 8169 : return LockMethods[lockmethodid]->lockModeNames[mode];
4049 : }
4050 :
4051 : #ifdef LOCK_DEBUG
4052 : /*
4053 : * Dump all locks in the given proc's myProcLocks lists.
4054 : *
4055 : * Caller is responsible for having acquired appropriate LWLocks.
4056 : */
4057 : void
4058 : DumpLocks(PGPROC *proc)
4059 : {
4060 : int i;
4061 :
4062 : if (proc == NULL)
4063 : return;
4064 :
4065 : if (proc->waitLock)
4066 : LOCK_PRINT("DumpLocks: waiting on", proc->waitLock, 0);
4067 :
4068 : for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
4069 : {
4070 : dlist_head *procLocks = &proc->myProcLocks[i];
4071 : dlist_iter iter;
4072 :
4073 : dlist_foreach(iter, procLocks)
4074 : {
4075 : PROCLOCK *proclock = dlist_container(PROCLOCK, procLink, iter.cur);
4076 : LOCK *lock = proclock->tag.myLock;
4077 :
4078 : Assert(proclock->tag.myProc == proc);
4079 : PROCLOCK_PRINT("DumpLocks", proclock);
4080 : LOCK_PRINT("DumpLocks", lock, 0);
4081 : }
4082 : }
9552 scrappy 4083 ECB : }
4084 :
4085 : /*
6330 tgl 4086 : * Dump all lmgr locks.
4087 : *
4088 : * Caller is responsible for having acquired appropriate LWLocks.
4089 : */
4090 : void
4091 : DumpAllLocks(void)
4092 : {
4093 : PGPROC *proc;
4094 : PROCLOCK *proclock;
4095 : LOCK *lock;
4096 : HASH_SEQ_STATUS status;
4097 :
4098 : proc = MyProc;
4099 :
4100 : if (proc && proc->waitLock)
8143 4101 : LOCK_PRINT("DumpAllLocks: waiting on", proc->waitLock, 0);
8993 scrappy 4102 :
6104 tgl 4103 : hash_seq_init(&status, LockMethodProcLockHash);
8993 scrappy 4104 :
4105 : while ((proclock = (PROCLOCK *) hash_seq_search(&status)) != NULL)
6104 tgl 4106 : {
6104 tgl 4107 EUB : PROCLOCK_PRINT("DumpAllLocks", proclock);
6328 tgl 4108 ECB :
4109 : lock = proclock->tag.myLock;
6104 4110 : if (lock)
4111 : LOCK_PRINT("DumpAllLocks", lock, 0);
4112 : else
4113 : elog(LOG, "DumpAllLocks: proclock->tag.myLock = NULL");
8993 scrappy 4114 : }
4115 : }
4116 : #endif /* LOCK_DEBUG */
4117 :
4118 : /*
6505 tgl 4119 : * LOCK 2PC resource manager's routines
4120 : */
4121 :
4122 : /*
4123 : * Re-acquire a lock belonging to a transaction that was prepared.
4124 : *
4125 : * Because this function is run at db startup, re-acquiring the locks should
6505 tgl 4126 EUB : * never conflict with running transactions because there are none. We
4127 : * assume that the lock state represented by the stored 2PC files is legal.
4128 : *
4129 : * When switching from Hot Standby mode to normal operation, the locks will
4130 : * be already held by the startup process. The locks are acquired for the new
4131 : * procs without checking for conflicts, so we don't get a conflict between the
4132 : * startup process and the dummy procs, even though we will momentarily have
4133 : * a situation where two procs are holding the same AccessExclusiveLock,
4134 : * which isn't normally possible because the conflict. If we're in standby
4135 : * mode, but a recovery snapshot hasn't been established yet, it's possible
4859 simon 4136 ECB : * that some but not all of the locks are already held by the startup process.
4137 : *
4138 : * This approach is simple, but also a bit dangerous, because if there isn't
4139 : * enough shared memory to acquire the locks, an error will be thrown, which
4140 : * is promoted to FATAL and recovery will abort, bringing down postmaster.
4141 : * A safer approach would be to transfer the locks like we do in
4142 : * AtPrepare_Locks, but then again, in hot standby mode it's possible for
4143 : * read-only backends to use up all the shared lock memory anyway, so that
4144 : * replaying the WAL record that needs to acquire a lock will throw an error
4145 : * and PANIC anyway.
4146 : */
4147 : void
6505 tgl 4148 GIC 79 : lock_twophase_recover(TransactionId xid, uint16 info,
4149 : void *recdata, uint32 len)
4150 : {
6505 tgl 4151 CBC 79 : TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
1504 michael 4152 79 : PGPROC *proc = TwoPhaseGetDummyProc(xid, false);
6385 bruce 4153 ECB : LOCKTAG *locktag;
4154 : LOCKMODE lockmode;
4155 : LOCKMETHODID lockmethodid;
4156 : LOCK *lock;
4157 : PROCLOCK *proclock;
4158 : PROCLOCKTAG proclocktag;
6505 tgl 4159 : bool found;
6104 4160 : uint32 hashcode;
4161 : uint32 proclock_hashcode;
6328 4162 : int partition;
4163 : LWLock *partitionLock;
4164 : LockMethod lockMethodTable;
4165 :
6505 tgl 4166 GIC 79 : Assert(len == sizeof(TwoPhaseLockRecord));
6505 tgl 4167 CBC 79 : locktag = &rec->locktag;
6505 tgl 4168 GIC 79 : lockmode = rec->lockmode;
4169 79 : lockmethodid = locktag->locktag_lockmethodid;
4170 :
6330 4171 79 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
6505 tgl 4172 LBC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
6330 tgl 4173 GIC 79 : lockMethodTable = LockMethods[lockmethodid];
4174 :
6104 tgl 4175 GBC 79 : hashcode = LockTagHashCode(locktag);
6104 tgl 4176 GIC 79 : partition = LockHashPartition(hashcode);
4177 79 : partitionLock = LockHashPartitionLock(hashcode);
4178 :
6328 4179 79 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4180 :
4181 : /*
4182 : * Find or create a lock with this tag.
6505 tgl 4183 EUB : */
6104 tgl 4184 GBC 79 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
4185 : locktag,
4186 : hashcode,
4187 : HASH_ENTER_NULL,
4188 : &found);
6505 4189 79 : if (!lock)
4190 : {
6328 tgl 4191 UBC 0 : LWLockRelease(partitionLock);
6505 4192 0 : ereport(ERROR,
4193 : (errcode(ERRCODE_OUT_OF_MEMORY),
4194 : errmsg("out of shared memory"),
4195 : errhint("You might need to increase max_locks_per_transaction.")));
4196 : }
4197 :
4198 : /*
4199 : * if it's a new lock object, initialize it
4200 : */
6505 tgl 4201 CBC 79 : if (!found)
4202 : {
4203 71 : lock->grantMask = 0;
4204 71 : lock->waitMask = 0;
81 andres 4205 GNC 71 : dlist_init(&lock->procLocks);
4206 71 : dclist_init(&lock->waitProcs);
6505 tgl 4207 GIC 71 : lock->nRequested = 0;
6505 tgl 4208 CBC 71 : lock->nGranted = 0;
4209 426 : MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
6505 tgl 4210 GIC 71 : MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
4211 : LOCK_PRINT("lock_twophase_recover: new", lock, lockmode);
4212 : }
4213 : else
4214 : {
4215 : LOCK_PRINT("lock_twophase_recover: found", lock, lockmode);
6505 tgl 4216 CBC 8 : Assert((lock->nRequested >= 0) && (lock->requested[lockmode] >= 0));
6505 tgl 4217 GIC 8 : Assert((lock->nGranted >= 0) && (lock->granted[lockmode] >= 0));
4218 8 : Assert(lock->nGranted <= lock->nRequested);
4219 : }
4220 :
4221 : /*
4222 : * Create the hash key for the proclock table.
6505 tgl 4223 ECB : */
6104 tgl 4224 CBC 79 : proclocktag.myLock = lock;
4225 79 : proclocktag.myProc = proc;
4226 :
6104 tgl 4227 GIC 79 : proclock_hashcode = ProcLockHashCode(&proclocktag, hashcode);
4228 :
4229 : /*
6505 tgl 4230 ECB : * Find or create a proclock entry with this tag
6505 tgl 4231 EUB : */
6104 tgl 4232 GIC 79 : proclock = (PROCLOCK *) hash_search_with_hash_value(LockMethodProcLockHash,
4233 : &proclocktag,
4234 : proclock_hashcode,
4235 : HASH_ENTER_NULL,
4236 : &found);
6505 4237 79 : if (!proclock)
4238 : {
4239 : /* Oops, not enough shmem for the proclock */
6505 tgl 4240 UIC 0 : if (lock->nRequested == 0)
6505 tgl 4241 ECB : {
4242 : /*
4243 : * There are no other requestors of this lock, so garbage-collect
4244 : * the lock object. We *must* do this to avoid a permanent leak
4245 : * of shared memory, because there won't be anything to cause
4246 : * anyone to release the lock object later.
4247 : */
81 andres 4248 UNC 0 : Assert(dlist_is_empty(&lock->procLocks));
6104 tgl 4249 LBC 0 : if (!hash_search_with_hash_value(LockMethodLockHash,
62 peter 4250 UNC 0 : &(lock->tag),
6104 tgl 4251 ECB : hashcode,
4252 : HASH_REMOVE,
4253 : NULL))
6505 tgl 4254 UIC 0 : elog(PANIC, "lock table corrupted");
4255 : }
6328 tgl 4256 LBC 0 : LWLockRelease(partitionLock);
6505 4257 0 : ereport(ERROR,
4258 : (errcode(ERRCODE_OUT_OF_MEMORY),
4259 : errmsg("out of shared memory"),
4260 : errhint("You might need to increase max_locks_per_transaction.")));
4261 : }
4262 :
4263 : /*
6505 tgl 4264 EUB : * If new, initialize the new entry
4265 : */
6505 tgl 4266 GIC 79 : if (!found)
6505 tgl 4267 EUB : {
2618 rhaas 4268 GIC 75 : Assert(proc->lockGroupLeader == NULL);
4269 75 : proclock->groupLeader = proc;
6505 tgl 4270 75 : proclock->holdMask = 0;
4271 75 : proclock->releaseMask = 0;
6505 tgl 4272 EUB : /* Add proclock to appropriate lists */
81 andres 4273 GNC 75 : dlist_push_tail(&lock->procLocks, &proclock->lockLink);
4274 75 : dlist_push_tail(&proc->myProcLocks[partition],
4275 : &proclock->procLink);
4276 : PROCLOCK_PRINT("lock_twophase_recover: new", proclock);
6505 tgl 4277 EUB : }
4278 : else
4279 : {
4280 : PROCLOCK_PRINT("lock_twophase_recover: found", proclock);
6505 tgl 4281 GBC 4 : Assert((proclock->holdMask & ~lock->grantMask) == 0);
4282 : }
6505 tgl 4283 EUB :
4284 : /*
4285 : * lock->nRequested and lock->requested[] count the total number of
4286 : * requests, whether granted or waiting, so increment those immediately.
4287 : */
6505 tgl 4288 GIC 79 : lock->nRequested++;
4289 79 : lock->requested[lockmode]++;
4290 79 : Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
4291 :
4292 : /*
4293 : * We shouldn't already hold the desired lock.
4294 : */
4295 79 : if (proclock->holdMask & LOCKBIT_ON(lockmode))
6505 tgl 4296 LBC 0 : elog(ERROR, "lock %s on object %u/%u/%u is already held",
4297 : lockMethodTable->lockModeNames[lockmode],
4298 : lock->tag.locktag_field1, lock->tag.locktag_field2,
6505 tgl 4299 ECB : lock->tag.locktag_field3);
4300 :
4301 : /*
4302 : * We ignore any possible conflicts and just grant ourselves the lock. Not
4303 : * only because we don't bother, but also to avoid deadlocks when
4304 : * switching from standby to normal mode. See function comment.
4305 : */
6505 tgl 4306 CBC 79 : GrantLock(lock, proclock, lockmode);
6505 tgl 4307 ECB :
4308 : /*
4334 rhaas 4309 : * Bump strong lock count, to make sure any fast-path lock requests won't
4334 rhaas 4310 EUB : * be granted without consulting the primary lock table.
4334 rhaas 4311 ECB : */
3966 rhaas 4312 GIC 79 : if (ConflictsWithRelationFastPath(&lock->tag, lockmode))
4334 rhaas 4313 ECB : {
3955 bruce 4314 CBC 13 : uint32 fasthashcode = FastPathStrongLockHashPartition(hashcode);
4315 :
4282 rhaas 4316 GIC 13 : SpinLockAcquire(&FastPathStrongRelationLocks->mutex);
4317 13 : FastPathStrongRelationLocks->count[fasthashcode]++;
4318 13 : SpinLockRelease(&FastPathStrongRelationLocks->mutex);
4319 : }
4320 :
6328 tgl 4321 79 : LWLockRelease(partitionLock);
6505 tgl 4322 CBC 79 : }
4323 :
4324 : /*
4859 simon 4325 ECB : * Re-acquire a lock belonging to a transaction that was prepared, when
3636 heikki.linnakangas 4326 : * starting up into hot standby mode.
4327 : */
4328 : void
4859 simon 4329 UIC 0 : lock_twophase_standby_recover(TransactionId xid, uint16 info,
4330 : void *recdata, uint32 len)
4331 : {
4332 0 : TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
4333 : LOCKTAG *locktag;
4334 : LOCKMODE lockmode;
4335 : LOCKMETHODID lockmethodid;
4336 :
4337 0 : Assert(len == sizeof(TwoPhaseLockRecord));
4338 0 : locktag = &rec->locktag;
4339 0 : lockmode = rec->lockmode;
4340 0 : lockmethodid = locktag->locktag_lockmethodid;
4341 :
4342 0 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
4343 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4344 :
4345 0 : if (lockmode == AccessExclusiveLock &&
4859 simon 4346 LBC 0 : locktag->locktag_type == LOCKTAG_RELATION)
4347 : {
4348 0 : StandbyAcquireAccessExclusiveLock(xid,
4349 : locktag->locktag_field1 /* dboid */ ,
2118 tgl 4350 ECB : locktag->locktag_field2 /* reloid */ );
4351 : }
4859 simon 4352 LBC 0 : }
4859 simon 4353 ECB :
4354 :
4355 : /*
6505 tgl 4356 : * 2PC processing routine for COMMIT PREPARED case.
4357 : *
4358 : * Find and release the lock indicated by the 2PC record.
4359 : */
4360 : void
6505 tgl 4361 GIC 850 : lock_twophase_postcommit(TransactionId xid, uint16 info,
4362 : void *recdata, uint32 len)
4363 : {
4364 850 : TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata;
1504 michael 4365 850 : PGPROC *proc = TwoPhaseGetDummyProc(xid, true);
4366 : LOCKTAG *locktag;
4367 : LOCKMETHODID lockmethodid;
4368 : LockMethod lockMethodTable;
6505 tgl 4369 ECB :
6505 tgl 4370 GIC 850 : Assert(len == sizeof(TwoPhaseLockRecord));
4371 850 : locktag = &rec->locktag;
4372 850 : lockmethodid = locktag->locktag_lockmethodid;
4373 :
6330 tgl 4374 CBC 850 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
6505 tgl 4375 UIC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
6330 tgl 4376 GIC 850 : lockMethodTable = LockMethods[lockmethodid];
4377 :
4334 rhaas 4378 850 : LockRefindAndRelease(lockMethodTable, proc, locktag, rec->lockmode, true);
6505 tgl 4379 CBC 850 : }
4380 :
6505 tgl 4381 ECB : /*
4382 : * 2PC processing routine for ROLLBACK PREPARED case.
4383 : *
4384 : * This is actually just the same as the COMMIT case.
4385 : */
4386 : void
6505 tgl 4387 GIC 121 : lock_twophase_postabort(TransactionId xid, uint16 info,
4388 : void *recdata, uint32 len)
4389 : {
4390 121 : lock_twophase_postcommit(xid, info, recdata, len);
4391 121 : }
4266 rhaas 4392 ECB :
4393 : /*
4394 : * VirtualXactLockTableInsert
4395 : *
4396 : * Take vxid lock via the fast-path. There can't be any pre-existing
4397 : * lockers, as we haven't advertised this vxid via the ProcArray yet.
4398 : *
4399 : * Since MyProc->fpLocalTransactionId will normally contain the same data
4400 : * as MyProc->lxid, you might wonder if we really need both. The
4401 : * difference is that MyProc->lxid is set and cleared unlocked, and
4402 : * examined by procarray.c, while fpLocalTransactionId is protected by
4403 : * fpInfoLock and is used only by the locking subsystem. Doing it this
4404 : * way makes it easier to verify that there are no funny race conditions.
4405 : *
4406 : * We don't bother recording this lock in the local lock table, since it's
4407 : * only ever released at the end of a transaction. Instead,
4408 : * LockReleaseAll() calls VirtualXactLockTableCleanup().
4409 : */
4410 : void
4266 rhaas 4411 GIC 486242 : VirtualXactLockTableInsert(VirtualTransactionId vxid)
4412 : {
4413 486242 : Assert(VirtualTransactionIdIsValid(vxid));
4414 :
1059 tgl 4415 486242 : LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE);
4416 :
4266 rhaas 4417 486242 : Assert(MyProc->backendId == vxid.backendId);
4266 rhaas 4418 CBC 486242 : Assert(MyProc->fpLocalTransactionId == InvalidLocalTransactionId);
4266 rhaas 4419 GIC 486242 : Assert(MyProc->fpVXIDLock == false);
4420 :
4266 rhaas 4421 CBC 486242 : MyProc->fpVXIDLock = true;
4266 rhaas 4422 GIC 486242 : MyProc->fpLocalTransactionId = vxid.localTransactionId;
4423 :
1059 tgl 4424 CBC 486242 : LWLockRelease(&MyProc->fpInfoLock);
4266 rhaas 4425 486242 : }
4426 :
4427 : /*
4428 : * VirtualXactLockTableCleanup
4429 : *
4430 : * Check whether a VXID lock has been materialized; if so, release it,
4431 : * unblocking waiters.
4432 : */
3783 simon 4433 ECB : void
3419 tgl 4434 GIC 486557 : VirtualXactLockTableCleanup(void)
4266 rhaas 4435 EUB : {
3955 bruce 4436 : bool fastpath;
4437 : LocalTransactionId lxid;
4438 :
4266 rhaas 4439 GIC 486557 : Assert(MyProc->backendId != InvalidBackendId);
4266 rhaas 4440 ECB :
4441 : /*
4442 : * Clean up shared memory state.
4443 : */
1059 tgl 4444 CBC 486557 : LWLockAcquire(&MyProc->fpInfoLock, LW_EXCLUSIVE);
4266 rhaas 4445 ECB :
4266 rhaas 4446 GIC 486557 : fastpath = MyProc->fpVXIDLock;
4447 486557 : lxid = MyProc->fpLocalTransactionId;
4448 486557 : MyProc->fpVXIDLock = false;
4266 rhaas 4449 CBC 486557 : MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
4266 rhaas 4450 ECB :
1059 tgl 4451 CBC 486557 : LWLockRelease(&MyProc->fpInfoLock);
4266 rhaas 4452 EUB :
4266 rhaas 4453 ECB : /*
4454 : * If fpVXIDLock has been cleared without touching fpLocalTransactionId,
4455 : * that means someone transferred the lock to the main lock table.
4456 : */
4266 rhaas 4457 GIC 486557 : if (!fastpath && LocalTransactionIdIsValid(lxid))
4458 : {
4459 : VirtualTransactionId vxid;
4460 : LOCKTAG locktag;
4461 :
4462 258 : vxid.backendId = MyBackendId;
4463 258 : vxid.localTransactionId = lxid;
4464 258 : SET_LOCKTAG_VIRTUALTRANSACTION(locktag, vxid);
4465 :
4466 258 : LockRefindAndRelease(LockMethods[DEFAULT_LOCKMETHOD], MyProc,
4467 : &locktag, ExclusiveLock, false);
4468 : }
4266 rhaas 4469 CBC 486557 : }
4470 :
4471 : /*
4472 : * XactLockForVirtualXact
533 noah 4473 ECB : *
4474 : * If TransactionIdIsValid(xid), this is essentially XactLockTableWait(xid,
4475 : * NULL, NULL, XLTW_None) or ConditionalXactLockTableWait(xid). Unlike those
4476 : * functions, it assumes "xid" is never a subtransaction and that "xid" is
4477 : * prepared, committed, or aborted.
4478 : *
4479 : * If !TransactionIdIsValid(xid), this locks every prepared XID having been
4480 : * known as "vxid" before its PREPARE TRANSACTION.
4481 : */
4482 : static bool
533 noah 4483 GIC 305 : XactLockForVirtualXact(VirtualTransactionId vxid,
4484 : TransactionId xid, bool wait)
4485 : {
4486 305 : bool more = false;
4487 :
4488 : /* There is no point to wait for 2PCs if you have no 2PCs. */
4489 305 : if (max_prepared_xacts == 0)
4490 101 : return true;
533 noah 4491 ECB :
4492 : do
4493 : {
4494 : LockAcquireResult lar;
4495 : LOCKTAG tag;
4496 :
4497 : /* Clear state from previous iterations. */
533 noah 4498 GIC 204 : if (more)
4499 : {
533 noah 4500 LBC 0 : xid = InvalidTransactionId;
533 noah 4501 UIC 0 : more = false;
533 noah 4502 ECB : }
4503 :
4504 : /* If we have no xid, try to find one. */
533 noah 4505 GIC 204 : if (!TransactionIdIsValid(xid))
533 noah 4506 CBC 98 : xid = TwoPhaseGetXidByVirtualXID(vxid, &more);
4507 204 : if (!TransactionIdIsValid(xid))
4508 : {
533 noah 4509 GIC 89 : Assert(!more);
4510 89 : return true;
4511 : }
4512 :
4513 : /* Check or wait for XID completion. */
533 noah 4514 CBC 115 : SET_LOCKTAG_TRANSACTION(tag, xid);
533 noah 4515 GIC 115 : lar = LockAcquire(&tag, ShareLock, false, !wait);
533 noah 4516 CBC 115 : if (lar == LOCKACQUIRE_NOT_AVAIL)
533 noah 4517 LBC 0 : return false;
533 noah 4518 GIC 115 : LockRelease(&tag, ShareLock, false);
4519 115 : } while (more);
4520 :
4521 115 : return true;
4522 : }
4523 :
4524 : /*
4266 rhaas 4525 ECB : * VirtualXactLock
4526 : *
4527 : * If wait = true, wait as long as the given VXID or any XID acquired by the
4528 : * same transaction is still running. Then, return true.
4529 : *
4530 : * If wait = false, just check whether that VXID or one of those XIDs is still
533 noah 4531 : * running, and return true or false.
4532 : */
4266 rhaas 4533 : bool
4266 rhaas 4534 CBC 345 : VirtualXactLock(VirtualTransactionId vxid, bool wait)
4535 : {
4266 rhaas 4536 ECB : LOCKTAG tag;
4537 : PGPROC *proc;
533 noah 4538 CBC 345 : TransactionId xid = InvalidTransactionId;
4539 :
4266 rhaas 4540 GBC 345 : Assert(VirtualTransactionIdIsValid(vxid));
4266 rhaas 4541 EUB :
533 noah 4542 GBC 345 : if (VirtualTransactionIdIsRecoveredPreparedXact(vxid))
4543 : /* no vxid lock; localTransactionId is a normal, locked XID */
533 noah 4544 GIC 1 : return XactLockForVirtualXact(vxid, vxid.localTransactionId, wait);
4545 :
4266 rhaas 4546 344 : SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
4266 rhaas 4547 ECB :
4548 : /*
4549 : * If a lock table entry must be made, this is the PGPROC on whose behalf
4550 : * it must be done. Note that the transaction might end or the PGPROC
4551 : * might be reassigned to a new backend before we get around to examining
4552 : * it, but it doesn't matter. If we find upon examination that the
4553 : * relevant lxid is no longer running here, that's enough to prove that
4554 : * it's no longer running anywhere.
4555 : */
4266 rhaas 4556 GIC 344 : proc = BackendIdGetProc(vxid.backendId);
4198 4557 344 : if (proc == NULL)
533 noah 4558 3 : return XactLockForVirtualXact(vxid, InvalidTransactionId, wait);
4559 :
4560 : /*
4561 : * We must acquire this lock before checking the backendId and lxid
3955 bruce 4562 ECB : * against the ones we're waiting for. The target backend will only set
4563 : * or clear lxid while holding this lock.
4564 : */
1059 tgl 4565 CBC 341 : LWLockAcquire(&proc->fpInfoLock, LW_EXCLUSIVE);
4566 :
4266 rhaas 4567 GIC 341 : if (proc->backendId != vxid.backendId
4266 rhaas 4568 CBC 341 : || proc->fpLocalTransactionId != vxid.localTransactionId)
4569 : {
533 noah 4570 ECB : /* VXID ended */
1059 tgl 4571 CBC 62 : LWLockRelease(&proc->fpInfoLock);
533 noah 4572 GIC 62 : return XactLockForVirtualXact(vxid, InvalidTransactionId, wait);
4573 : }
4574 :
4575 : /*
4576 : * If we aren't asked to wait, there's no need to set up a lock table
4577 : * entry. The transaction is still in progress, so just return false.
4578 : */
4266 rhaas 4579 279 : if (!wait)
4266 rhaas 4580 ECB : {
1059 tgl 4581 GIC 15 : LWLockRelease(&proc->fpInfoLock);
4266 rhaas 4582 CBC 15 : return false;
4583 : }
4584 :
4585 : /*
4586 : * OK, we're going to need to sleep on the VXID. But first, we must set
3743 tgl 4587 ECB : * up the primary lock table entry, if needed (ie, convert the proc's
4588 : * fast-path lock on its VXID to a regular lock).
4266 rhaas 4589 : */
4266 rhaas 4590 GBC 264 : if (proc->fpVXIDLock)
4591 : {
4266 rhaas 4592 ECB : PROCLOCK *proclock;
4593 : uint32 hashcode;
3359 4594 : LWLock *partitionLock;
4595 :
4266 rhaas 4596 CBC 258 : hashcode = LockTagHashCode(&tag);
4597 :
3743 tgl 4598 GIC 258 : partitionLock = LockHashPartitionLock(hashcode);
4599 258 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4600 :
4266 rhaas 4601 CBC 258 : proclock = SetupLockInTable(LockMethods[DEFAULT_LOCKMETHOD], proc,
4602 : &tag, hashcode, ExclusiveLock);
4603 258 : if (!proclock)
3743 tgl 4604 ECB : {
3743 tgl 4605 UIC 0 : LWLockRelease(partitionLock);
1059 tgl 4606 LBC 0 : LWLockRelease(&proc->fpInfoLock);
4266 rhaas 4607 UIC 0 : ereport(ERROR,
4266 rhaas 4608 ECB : (errcode(ERRCODE_OUT_OF_MEMORY),
4609 : errmsg("out of shared memory"),
4610 : errhint("You might need to increase max_locks_per_transaction.")));
4611 : }
4266 rhaas 4612 GIC 258 : GrantLock(proclock->tag.myLock, proclock, ExclusiveLock);
4613 :
3743 tgl 4614 258 : LWLockRelease(partitionLock);
4615 :
4266 rhaas 4616 258 : proc->fpVXIDLock = false;
4617 : }
4618 :
4619 : /*
4620 : * If the proc has an XID now, we'll avoid a TwoPhaseGetXidByVirtualXID()
4621 : * search. The proc might have assigned this XID but not yet locked it,
4622 : * in which case the proc will lock this XID before releasing the VXID.
4623 : * The fpInfoLock critical section excludes VirtualXactLockTableCleanup(),
4624 : * so we won't save an XID of a different VXID. It doesn't matter whether
4625 : * we save this before or after setting up the primary lock table entry.
4626 : */
533 noah 4627 264 : xid = proc->xid;
4628 :
4629 : /* Done with proc->fpLockBits */
1059 tgl 4630 264 : LWLockRelease(&proc->fpInfoLock);
4631 :
4632 : /* Time to wait. */
4266 rhaas 4633 264 : (void) LockAcquire(&tag, ShareLock, false, false);
4634 :
4635 239 : LockRelease(&tag, ShareLock, false);
533 noah 4636 239 : return XactLockForVirtualXact(vxid, xid, wait);
4637 : }
4638 :
4639 : /*
4640 : * LockWaiterCount
4641 : *
4642 : * Find the number of lock requester on this locktag
4643 : */
4644 : int
2557 rhaas 4645 114052 : LockWaiterCount(const LOCKTAG *locktag)
4646 : {
4647 114052 : LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
4648 : LOCK *lock;
4649 : bool found;
4650 : uint32 hashcode;
4651 : LWLock *partitionLock;
4652 114052 : int waiters = 0;
4653 :
4654 114052 : if (lockmethodid <= 0 || lockmethodid >= lengthof(LockMethods))
2557 rhaas 4655 UIC 0 : elog(ERROR, "unrecognized lock method: %d", lockmethodid);
4656 :
2557 rhaas 4657 GIC 114052 : hashcode = LockTagHashCode(locktag);
4658 114052 : partitionLock = LockHashPartitionLock(hashcode);
4659 114052 : LWLockAcquire(partitionLock, LW_EXCLUSIVE);
4660 :
4661 114052 : lock = (LOCK *) hash_search_with_hash_value(LockMethodLockHash,
4662 : locktag,
4663 : hashcode,
4664 : HASH_FIND,
4665 : &found);
4666 114052 : if (found)
4667 : {
4668 36 : Assert(lock != NULL);
4669 36 : waiters = lock->nRequested;
4670 : }
4671 114052 : LWLockRelease(partitionLock);
4672 :
4673 114052 : return waiters;
4674 : }
|