PostgreSQL Source Code git master
Loading...
Searching...
No Matches
lockfuncs.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * lockfuncs.c
4 * Functions for SQL access to various lock-manager capabilities.
5 *
6 * Copyright (c) 2002-2026, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/backend/utils/adt/lockfuncs.c
10 *
11 *-------------------------------------------------------------------------
12 */
13#include "postgres.h"
14
15#include "access/htup_details.h"
16#include "funcapi.h"
17#include "miscadmin.h"
19#include "utils/array.h"
20#include "utils/builtins.h"
21
22
23/*
24 * This must match enum LockTagType! Also, be sure to document any changes
25 * in the docs for the pg_locks view and update the WaitEventLOCK section in
26 * src/backend/utils/activity/wait_event_names.txt.
27 */
28const char *const LockTagTypeNames[] = {
29 "relation",
30 "extend",
31 "frozenid",
32 "page",
33 "tuple",
34 "transactionid",
35 "virtualxid",
36 "spectoken",
37 "object",
38 "userlock",
39 "advisory",
40 "applytransaction"
41};
42
44 "array length mismatch");
45
46/* This must match enum PredicateLockTargetType (predicate_internals.h) */
47static const char *const PredicateLockTagTypeNames[] = {
48 "relation",
49 "page",
50 "tuple"
51};
52
54 "array length mismatch");
55
56/* Working status for pg_lock_status */
57typedef struct
58{
59 LockData *lockData; /* state data from lmgr */
60 int currIdx; /* current PROCLOCK index */
61 PredicateLockData *predLockData; /* state data for pred locks */
62 int predLockIdx; /* current index for pred lock */
64
65/* Number of columns in pg_locks output */
66#define NUM_LOCK_STATUS_COLUMNS 16
67
68/*
69 * VXIDGetDatum - Construct a text representation of a VXID
70 *
71 * This is currently only used in pg_lock_status, so we put it here.
72 */
73static Datum
75{
76 /*
77 * The representation is "<procNumber>/<lxid>", decimal and unsigned
78 * decimal respectively. Note that elog.c also knows how to format a
79 * vxid.
80 */
81 char vxidstr[32];
82
83 snprintf(vxidstr, sizeof(vxidstr), "%d/%u", procNumber, lxid);
84
86}
87
88
89/*
90 * pg_lock_status - produce a view with one row per held or awaited lock mode
91 */
94{
97 LockData *lockData;
98 PredicateLockData *predLockData;
99
100 if (SRF_IS_FIRSTCALL())
101 {
102 TupleDesc tupdesc;
103 MemoryContext oldcontext;
104
105 /* create a function context for cross-call persistence */
107
108 /*
109 * switch to memory context appropriate for multiple function calls
110 */
111 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
112
113 /* build tupdesc for result tuples */
114 /* this had better match function's declaration in pg_proc.h */
116 TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
117 TEXTOID, -1, 0);
118 TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
119 OIDOID, -1, 0);
120 TupleDescInitEntry(tupdesc, (AttrNumber) 3, "relation",
121 OIDOID, -1, 0);
122 TupleDescInitEntry(tupdesc, (AttrNumber) 4, "page",
123 INT4OID, -1, 0);
124 TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple",
125 INT2OID, -1, 0);
126 TupleDescInitEntry(tupdesc, (AttrNumber) 6, "virtualxid",
127 TEXTOID, -1, 0);
128 TupleDescInitEntry(tupdesc, (AttrNumber) 7, "transactionid",
129 XIDOID, -1, 0);
130 TupleDescInitEntry(tupdesc, (AttrNumber) 8, "classid",
131 OIDOID, -1, 0);
132 TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objid",
133 OIDOID, -1, 0);
134 TupleDescInitEntry(tupdesc, (AttrNumber) 10, "objsubid",
135 INT2OID, -1, 0);
136 TupleDescInitEntry(tupdesc, (AttrNumber) 11, "virtualtransaction",
137 TEXTOID, -1, 0);
138 TupleDescInitEntry(tupdesc, (AttrNumber) 12, "pid",
139 INT4OID, -1, 0);
140 TupleDescInitEntry(tupdesc, (AttrNumber) 13, "mode",
141 TEXTOID, -1, 0);
142 TupleDescInitEntry(tupdesc, (AttrNumber) 14, "granted",
143 BOOLOID, -1, 0);
144 TupleDescInitEntry(tupdesc, (AttrNumber) 15, "fastpath",
145 BOOLOID, -1, 0);
146 TupleDescInitEntry(tupdesc, (AttrNumber) 16, "waitstart",
147 TIMESTAMPTZOID, -1, 0);
148
149 TupleDescFinalize(tupdesc);
150 funcctx->tuple_desc = BlessTupleDesc(tupdesc);
151
152 /*
153 * Collect all the locking information that we will format and send
154 * out as a result set.
155 */
157 funcctx->user_fctx = mystatus;
158
159 mystatus->lockData = GetLockStatusData();
160 mystatus->currIdx = 0;
161 mystatus->predLockData = GetPredicateLockStatusData();
162 mystatus->predLockIdx = 0;
163
164 MemoryContextSwitchTo(oldcontext);
165 }
166
168 mystatus = (PG_Lock_Status *) funcctx->user_fctx;
169 lockData = mystatus->lockData;
170
171 while (mystatus->currIdx < lockData->nelements)
172 {
173 bool granted;
174 LOCKMODE mode = 0;
175 const char *locktypename;
176 char tnbuf[32];
178 bool nulls[NUM_LOCK_STATUS_COLUMNS] = {0};
179 HeapTuple tuple;
180 Datum result;
182
183 instance = &(lockData->locks[mystatus->currIdx]);
184
185 /*
186 * Look to see if there are any held lock modes in this PROCLOCK. If
187 * so, report, and destructively modify lockData so we don't report
188 * again.
189 */
190 granted = false;
191 if (instance->holdMask)
192 {
193 for (mode = 0; mode < MAX_LOCKMODES; mode++)
194 {
195 if (instance->holdMask & LOCKBIT_ON(mode))
196 {
197 granted = true;
199 break;
200 }
201 }
202 }
203
204 /*
205 * If no (more) held modes to report, see if PROC is waiting for a
206 * lock on this lock.
207 */
208 if (!granted)
209 {
210 if (instance->waitLockMode != NoLock)
211 {
212 /* Yes, so report it with proper mode */
213 mode = instance->waitLockMode;
214
215 /*
216 * We are now done with this PROCLOCK, so advance pointer to
217 * continue with next one on next call.
218 */
219 mystatus->currIdx++;
220 }
221 else
222 {
223 /*
224 * Okay, we've displayed all the locks associated with this
225 * PROCLOCK, proceed to the next one.
226 */
227 mystatus->currIdx++;
228 continue;
229 }
230 }
231
232 /*
233 * Form tuple with appropriate data.
234 */
235
236 if (instance->locktag.locktag_type <= LOCKTAG_LAST_TYPE)
237 locktypename = LockTagTypeNames[instance->locktag.locktag_type];
238 else
239 {
240 snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
241 (int) instance->locktag.locktag_type);
243 }
245
246 switch ((LockTagType) instance->locktag.locktag_type)
247 {
248 case LOCKTAG_RELATION:
250 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
251 values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
252 nulls[3] = true;
253 nulls[4] = true;
254 nulls[5] = true;
255 nulls[6] = true;
256 nulls[7] = true;
257 nulls[8] = true;
258 nulls[9] = true;
259 break;
261 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
262 nulls[2] = true;
263 nulls[3] = true;
264 nulls[4] = true;
265 nulls[5] = true;
266 nulls[6] = true;
267 nulls[7] = true;
268 nulls[8] = true;
269 nulls[9] = true;
270 break;
271 case LOCKTAG_PAGE:
272 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
273 values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
274 values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
275 nulls[4] = true;
276 nulls[5] = true;
277 nulls[6] = true;
278 nulls[7] = true;
279 nulls[8] = true;
280 nulls[9] = true;
281 break;
282 case LOCKTAG_TUPLE:
283 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
284 values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
285 values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
286 values[4] = UInt16GetDatum(instance->locktag.locktag_field4);
287 nulls[5] = true;
288 nulls[6] = true;
289 nulls[7] = true;
290 nulls[8] = true;
291 nulls[9] = true;
292 break;
294 values[6] =
295 TransactionIdGetDatum(instance->locktag.locktag_field1);
296 nulls[1] = true;
297 nulls[2] = true;
298 nulls[3] = true;
299 nulls[4] = true;
300 nulls[5] = true;
301 nulls[7] = true;
302 nulls[8] = true;
303 nulls[9] = true;
304 break;
306 values[5] = VXIDGetDatum(instance->locktag.locktag_field1,
307 instance->locktag.locktag_field2);
308 nulls[1] = true;
309 nulls[2] = true;
310 nulls[3] = true;
311 nulls[4] = true;
312 nulls[6] = true;
313 nulls[7] = true;
314 nulls[8] = true;
315 nulls[9] = true;
316 break;
318 values[6] =
319 TransactionIdGetDatum(instance->locktag.locktag_field1);
320 values[8] = ObjectIdGetDatum(instance->locktag.locktag_field2);
321 nulls[1] = true;
322 nulls[2] = true;
323 nulls[3] = true;
324 nulls[4] = true;
325 nulls[5] = true;
326 nulls[7] = true;
327 nulls[9] = true;
328 break;
330 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
331 values[8] = ObjectIdGetDatum(instance->locktag.locktag_field2);
332 values[6] = ObjectIdGetDatum(instance->locktag.locktag_field3);
333 values[9] = UInt16GetDatum(instance->locktag.locktag_field4);
334 nulls[2] = true;
335 nulls[3] = true;
336 nulls[4] = true;
337 nulls[5] = true;
338 nulls[7] = true;
339 break;
340 case LOCKTAG_OBJECT:
341 case LOCKTAG_USERLOCK:
342 case LOCKTAG_ADVISORY:
343 default: /* treat unknown locktags like OBJECT */
344 values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
345 values[7] = ObjectIdGetDatum(instance->locktag.locktag_field2);
346 values[8] = ObjectIdGetDatum(instance->locktag.locktag_field3);
347 values[9] = UInt16GetDatum(instance->locktag.locktag_field4);
348 nulls[2] = true;
349 nulls[3] = true;
350 nulls[4] = true;
351 nulls[5] = true;
352 nulls[6] = true;
353 break;
354 }
355
356 values[10] = VXIDGetDatum(instance->vxid.procNumber, instance->vxid.localTransactionId);
357 if (instance->pid != 0)
358 values[11] = Int32GetDatum(instance->pid);
359 else
360 nulls[11] = true;
361 values[12] = CStringGetTextDatum(GetLockmodeName(instance->locktag.locktag_lockmethodid, mode));
362 values[13] = BoolGetDatum(granted);
363 values[14] = BoolGetDatum(instance->fastpath);
364 if (!granted && instance->waitStart != 0)
365 values[15] = TimestampTzGetDatum(instance->waitStart);
366 else
367 nulls[15] = true;
368
369 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
370 result = HeapTupleGetDatum(tuple);
371 SRF_RETURN_NEXT(funcctx, result);
372 }
373
374 /*
375 * Have returned all regular locks. Now start on the SIREAD predicate
376 * locks.
377 */
378 predLockData = mystatus->predLockData;
379 if (mystatus->predLockIdx < predLockData->nelements)
380 {
382
383 PREDICATELOCKTARGETTAG *predTag = &(predLockData->locktags[mystatus->predLockIdx]);
384 SERIALIZABLEXACT *xact = &(predLockData->xacts[mystatus->predLockIdx]);
386 bool nulls[NUM_LOCK_STATUS_COLUMNS] = {0};
387 HeapTuple tuple;
388 Datum result;
389
390 mystatus->predLockIdx++;
391
392 /*
393 * Form tuple with appropriate data.
394 */
395
396 /* lock type */
398
400
401 /* lock target */
406 else
407 nulls[4] = true;
408 if ((lockType == PREDLOCKTAG_TUPLE) ||
411 else
412 nulls[3] = true;
413
414 /* these fields are targets for other types of locks */
415 nulls[5] = true; /* virtualxid */
416 nulls[6] = true; /* transactionid */
417 nulls[7] = true; /* classid */
418 nulls[8] = true; /* objid */
419 nulls[9] = true; /* objsubid */
420
421 /* lock holder */
422 values[10] = VXIDGetDatum(xact->vxid.procNumber,
423 xact->vxid.localTransactionId);
424 if (xact->pid != 0)
425 values[11] = Int32GetDatum(xact->pid);
426 else
427 nulls[11] = true;
428
429 /*
430 * Lock mode. Currently all predicate locks are SIReadLocks, which are
431 * always held (never waiting) and have no fast path
432 */
433 values[12] = CStringGetTextDatum("SIReadLock");
434 values[13] = BoolGetDatum(true);
435 values[14] = BoolGetDatum(false);
436 nulls[15] = true;
437
438 tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
439 result = HeapTupleGetDatum(tuple);
440 SRF_RETURN_NEXT(funcctx, result);
441 }
442
444}
445
446
447/*
448 * pg_blocking_pids - produce an array of the PIDs blocking given PID
449 *
450 * The reported PIDs are those that hold a lock conflicting with blocked_pid's
451 * current request (hard block), or are requesting such a lock and are ahead
452 * of blocked_pid in the lock's wait queue (soft block).
453 *
454 * In parallel-query cases, we report all PIDs blocking any member of the
455 * given PID's lock group, and the reported PIDs are those of the blocking
456 * PIDs' lock group leaders. This allows callers to compare the result to
457 * lists of clients' pg_backend_pid() results even during a parallel query.
458 *
459 * Parallel query makes it possible for there to be duplicate PIDs in the
460 * result (either because multiple waiters are blocked by same PID, or
461 * because multiple blockers have same group leader PID). We do not bother
462 * to eliminate such duplicates from the result.
463 *
464 * We need not consider predicate locks here, since those don't block anything.
465 */
466Datum
468{
471 int narrayelems;
472 BlockedProcsData *lockData; /* state data from lmgr */
473 int i,
474 j;
475
476 /* Collect a snapshot of lock manager state */
478
479 /* We can't need more output entries than there are reported PROCLOCKs */
480 arrayelems = (Datum *) palloc(lockData->nlocks * sizeof(Datum));
481 narrayelems = 0;
482
483 /* For each blocked proc in the lock group ... */
484 for (i = 0; i < lockData->nprocs; i++)
485 {
486 BlockedProcData *bproc = &lockData->procs[i];
487 LockInstanceData *instances = &lockData->locks[bproc->first_lock];
488 int *preceding_waiters = &lockData->waiter_pids[bproc->first_waiter];
491 int conflictMask;
492
493 /*
494 * Locate the blocked proc's own entry in the LockInstanceData array.
495 * There should be exactly one matching entry.
496 */
498 for (j = 0; j < bproc->num_locks; j++)
499 {
501
502 if (instance->pid == bproc->pid)
503 {
506 }
507 }
509
511 conflictMask = lockMethodTable->conflictTab[blocked_instance->waitLockMode];
512
513 /* Now scan the PROCLOCK data for conflicting procs */
514 for (j = 0; j < bproc->num_locks; j++)
515 {
517
518 /* A proc never blocks itself, so ignore that entry */
520 continue;
521 /* Members of same lock group never block each other, either */
522 if (instance->leaderPid == blocked_instance->leaderPid)
523 continue;
524
525 if (conflictMask & instance->holdMask)
526 {
527 /* hard block: blocked by lock already held by this entry */
528 }
529 else if (instance->waitLockMode != NoLock &&
530 (conflictMask & LOCKBIT_ON(instance->waitLockMode)))
531 {
532 /* conflict in lock requests; who's in front in wait queue? */
533 bool ahead = false;
534 int k;
535
536 for (k = 0; k < bproc->num_waiters; k++)
537 {
538 if (preceding_waiters[k] == instance->pid)
539 {
540 /* soft block: this entry is ahead of blocked proc */
541 ahead = true;
542 break;
543 }
544 }
545 if (!ahead)
546 continue; /* not blocked by this entry */
547 }
548 else
549 {
550 /* not blocked by this entry */
551 continue;
552 }
553
554 /* blocked by this entry, so emit a record */
556 }
557 }
558
559 /* Assert we didn't overrun arrayelems[] */
561
563}
564
565
566/*
567 * pg_safe_snapshot_blocking_pids - produce an array of the PIDs blocking
568 * given PID from getting a safe snapshot
569 *
570 * XXX this does not consider parallel-query cases; not clear how big a
571 * problem that is in practice
572 */
573Datum
575{
577 int *blockers;
578 int num_blockers;
580
581 /* A buffer big enough for any possible blocker list without truncation */
582 blockers = (int *) palloc(MaxBackends * sizeof(int));
583
584 /* Collect a snapshot of processes waited for by GetSafeSnapshot */
587
588 /* Convert int array to Datum array */
589 if (num_blockers > 0)
590 {
591 int i;
592
594 for (i = 0; i < num_blockers; ++i)
595 blocker_datums[i] = Int32GetDatum(blockers[i]);
596 }
597 else
599
601}
602
603
604/*
605 * Functions for manipulating advisory locks
606 *
607 * We make use of the locktag fields as follows:
608 *
609 * field1: MyDatabaseId ... ensures locks are local to each database
610 * field2: first of 2 int4 keys, or high-order half of an int8 key
611 * field3: second of 2 int4 keys, or low-order half of an int8 key
612 * field4: 1 if using an int8 key, 2 if using 2 int4 keys
613 */
614#define SET_LOCKTAG_INT64(tag, key64) \
615 SET_LOCKTAG_ADVISORY(tag, \
616 MyDatabaseId, \
617 (uint32) ((key64) >> 32), \
618 (uint32) (key64), \
619 1)
620#define SET_LOCKTAG_INT32(tag, key1, key2) \
621 SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key1, key2, 2)
622
623/*
624 * pg_advisory_lock(int8) - acquire exclusive lock on an int8 key
625 */
626Datum
628{
629 int64 key = PG_GETARG_INT64(0);
630 LOCKTAG tag;
631
632 SET_LOCKTAG_INT64(tag, key);
633
634 (void) LockAcquire(&tag, ExclusiveLock, true, false);
635
637}
638
639/*
640 * pg_advisory_xact_lock(int8) - acquire xact scoped
641 * exclusive lock on an int8 key
642 */
643Datum
645{
646 int64 key = PG_GETARG_INT64(0);
647 LOCKTAG tag;
648
649 SET_LOCKTAG_INT64(tag, key);
650
651 (void) LockAcquire(&tag, ExclusiveLock, false, false);
652
654}
655
656/*
657 * pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
658 */
659Datum
661{
662 int64 key = PG_GETARG_INT64(0);
663 LOCKTAG tag;
664
665 SET_LOCKTAG_INT64(tag, key);
666
667 (void) LockAcquire(&tag, ShareLock, true, false);
668
670}
671
672/*
673 * pg_advisory_xact_lock_shared(int8) - acquire xact scoped
674 * share lock on an int8 key
675 */
676Datum
678{
679 int64 key = PG_GETARG_INT64(0);
680 LOCKTAG tag;
681
682 SET_LOCKTAG_INT64(tag, key);
683
684 (void) LockAcquire(&tag, ShareLock, false, false);
685
687}
688
689/*
690 * pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
691 *
692 * Returns true if successful, false if lock not available
693 */
694Datum
696{
697 int64 key = PG_GETARG_INT64(0);
698 LOCKTAG tag;
700
701 SET_LOCKTAG_INT64(tag, key);
702
703 res = LockAcquire(&tag, ExclusiveLock, true, true);
704
706}
707
708/*
709 * pg_try_advisory_xact_lock(int8) - acquire xact scoped
710 * exclusive lock on an int8 key, no wait
711 *
712 * Returns true if successful, false if lock not available
713 */
714Datum
716{
717 int64 key = PG_GETARG_INT64(0);
718 LOCKTAG tag;
720
721 SET_LOCKTAG_INT64(tag, key);
722
723 res = LockAcquire(&tag, ExclusiveLock, false, true);
724
726}
727
728/*
729 * pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
730 *
731 * Returns true if successful, false if lock not available
732 */
733Datum
735{
736 int64 key = PG_GETARG_INT64(0);
737 LOCKTAG tag;
739
740 SET_LOCKTAG_INT64(tag, key);
741
742 res = LockAcquire(&tag, ShareLock, true, true);
743
745}
746
747/*
748 * pg_try_advisory_xact_lock_shared(int8) - acquire xact scoped
749 * share lock on an int8 key, no wait
750 *
751 * Returns true if successful, false if lock not available
752 */
753Datum
755{
756 int64 key = PG_GETARG_INT64(0);
757 LOCKTAG tag;
759
760 SET_LOCKTAG_INT64(tag, key);
761
762 res = LockAcquire(&tag, ShareLock, false, true);
763
765}
766
767/*
768 * pg_advisory_unlock(int8) - release exclusive lock on an int8 key
769 *
770 * Returns true if successful, false if lock was not held
771*/
772Datum
774{
775 int64 key = PG_GETARG_INT64(0);
776 LOCKTAG tag;
777 bool res;
778
779 SET_LOCKTAG_INT64(tag, key);
780
781 res = LockRelease(&tag, ExclusiveLock, true);
782
783 PG_RETURN_BOOL(res);
784}
785
786/*
787 * pg_advisory_unlock_shared(int8) - release share lock on an int8 key
788 *
789 * Returns true if successful, false if lock was not held
790 */
791Datum
793{
794 int64 key = PG_GETARG_INT64(0);
795 LOCKTAG tag;
796 bool res;
797
798 SET_LOCKTAG_INT64(tag, key);
799
800 res = LockRelease(&tag, ShareLock, true);
801
802 PG_RETURN_BOOL(res);
803}
804
805/*
806 * pg_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys
807 */
808Datum
810{
813 LOCKTAG tag;
814
816
817 (void) LockAcquire(&tag, ExclusiveLock, true, false);
818
820}
821
822/*
823 * pg_advisory_xact_lock(int4, int4) - acquire xact scoped
824 * exclusive lock on 2 int4 keys
825 */
826Datum
828{
831 LOCKTAG tag;
832
834
835 (void) LockAcquire(&tag, ExclusiveLock, false, false);
836
838}
839
840/*
841 * pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
842 */
843Datum
845{
848 LOCKTAG tag;
849
851
852 (void) LockAcquire(&tag, ShareLock, true, false);
853
855}
856
857/*
858 * pg_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
859 * share lock on 2 int4 keys
860 */
861Datum
863{
866 LOCKTAG tag;
867
869
870 (void) LockAcquire(&tag, ShareLock, false, false);
871
873}
874
875/*
876 * pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
877 *
878 * Returns true if successful, false if lock not available
879 */
880Datum
894
895/*
896 * pg_try_advisory_xact_lock(int4, int4) - acquire xact scoped
897 * exclusive lock on 2 int4 keys, no wait
898 *
899 * Returns true if successful, false if lock not available
900 */
901Datum
915
916/*
917 * pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
918 *
919 * Returns true if successful, false if lock not available
920 */
921Datum
935
936/*
937 * pg_try_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
938 * share lock on 2 int4 keys, no wait
939 *
940 * Returns true if successful, false if lock not available
941 */
942Datum
956
957/*
958 * pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
959 *
960 * Returns true if successful, false if lock was not held
961*/
962Datum
964{
967 LOCKTAG tag;
968 bool res;
969
971
972 res = LockRelease(&tag, ExclusiveLock, true);
973
974 PG_RETURN_BOOL(res);
975}
976
977/*
978 * pg_advisory_unlock_shared(int4, int4) - release share lock on 2 int4 keys
979 *
980 * Returns true if successful, false if lock was not held
981 */
982Datum
984{
987 LOCKTAG tag;
988 bool res;
989
991
992 res = LockRelease(&tag, ShareLock, true);
993
994 PG_RETURN_BOOL(res);
995}
996
997/*
998 * pg_advisory_unlock_all() - release all advisory locks
999 */
1000Datum
#define PG_RETURN_ARRAYTYPE_P(x)
Definition array.h:265
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
int16 AttrNumber
Definition attnum.h:21
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define Assert(condition)
Definition c.h:945
int64_t int64
Definition c.h:615
int32_t int32
Definition c.h:614
#define lengthof(array)
Definition c.h:875
uint32 LocalTransactionId
Definition c.h:740
#define StaticAssertDecl(condition, errmessage)
Definition c.h:1010
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
#define palloc_object(type)
Definition fe_memutils.h:74
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
int MaxBackends
Definition globals.c:146
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1037
int j
Definition isn.c:78
int i
Definition isn.c:77
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition lock.c:809
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition lock.c:2102
BlockedProcsData * GetBlockerStatusData(int blocked_pid)
Definition lock.c:3996
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition lock.c:4252
void LockReleaseSession(LOCKMETHODID lockmethodid)
Definition lock.c:2581
LockData * GetLockStatusData(void)
Definition lock.c:3793
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
Definition lock.c:539
#define LOCKBIT_OFF(lockmode)
Definition lock.h:88
#define MAX_LOCKMODES
Definition lock.h:85
#define LOCKBIT_ON(lockmode)
Definition lock.h:87
LockAcquireResult
Definition lock.h:331
@ LOCKACQUIRE_NOT_AVAIL
Definition lock.h:332
int LOCKMODE
Definition lockdefs.h:26
#define NoLock
Definition lockdefs.h:34
#define ExclusiveLock
Definition lockdefs.h:42
#define ShareLock
Definition lockdefs.h:40
Datum pg_advisory_lock_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:809
#define SET_LOCKTAG_INT64(tag, key64)
Definition lockfuncs.c:614
Datum pg_try_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:902
Datum pg_advisory_unlock_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:773
Datum pg_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:844
Datum pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
Definition lockfuncs.c:574
Datum pg_advisory_lock_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:627
Datum pg_try_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:754
Datum pg_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:644
Datum pg_try_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:922
static Datum VXIDGetDatum(ProcNumber procNumber, LocalTransactionId lxid)
Definition lockfuncs.c:74
Datum pg_try_advisory_lock_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:881
#define SET_LOCKTAG_INT32(tag, key1, key2)
Definition lockfuncs.c:620
#define NUM_LOCK_STATUS_COLUMNS
Definition lockfuncs.c:66
Datum pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:983
Datum pg_advisory_unlock_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:963
static const char *const PredicateLockTagTypeNames[]
Definition lockfuncs.c:47
Datum pg_try_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:734
Datum pg_lock_status(PG_FUNCTION_ARGS)
Definition lockfuncs.c:93
Datum pg_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:827
Datum pg_try_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:715
Datum pg_blocking_pids(PG_FUNCTION_ARGS)
Definition lockfuncs.c:467
Datum pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:660
Datum pg_try_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:943
Datum pg_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:677
Datum pg_advisory_unlock_shared_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:792
Datum pg_try_advisory_lock_int8(PG_FUNCTION_ARGS)
Definition lockfuncs.c:695
Datum pg_advisory_unlock_all(PG_FUNCTION_ARGS)
Definition lockfuncs.c:1001
const char *const LockTagTypeNames[]
Definition lockfuncs.c:28
Datum pg_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
Definition lockfuncs.c:862
LockTagType
Definition locktag.h:36
@ LOCKTAG_OBJECT
Definition locktag.h:45
@ LOCKTAG_RELATION_EXTEND
Definition locktag.h:38
@ LOCKTAG_RELATION
Definition locktag.h:37
@ LOCKTAG_TUPLE
Definition locktag.h:41
@ LOCKTAG_SPECULATIVE_TOKEN
Definition locktag.h:44
@ LOCKTAG_APPLY_TRANSACTION
Definition locktag.h:48
@ LOCKTAG_USERLOCK
Definition locktag.h:46
@ LOCKTAG_DATABASE_FROZEN_IDS
Definition locktag.h:39
@ LOCKTAG_VIRTUALTRANSACTION
Definition locktag.h:43
@ LOCKTAG_TRANSACTION
Definition locktag.h:42
@ LOCKTAG_PAGE
Definition locktag.h:40
@ LOCKTAG_ADVISORY
Definition locktag.h:47
#define USER_LOCKMETHOD
Definition locktag.h:26
#define LOCKTAG_LAST_TYPE
Definition locktag.h:52
void * palloc(Size size)
Definition mcxt.c:1387
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static PgChecksumMode mode
#define snprintf
Definition port.h:260
static Datum TransactionIdGetDatum(TransactionId X)
Definition postgres.h:292
static Datum UInt16GetDatum(uint16 X)
Definition postgres.h:192
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static Datum UInt32GetDatum(uint32 X)
Definition postgres.h:232
PredicateLockData * GetPredicateLockStatusData(void)
Definition predicate.c:1456
int GetSafeSnapshotBlockingPids(int blocked_pid, int *output, int output_size)
Definition predicate.c:1637
PredicateLockTargetType
@ PREDLOCKTAG_PAGE
@ PREDLOCKTAG_TUPLE
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag)
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag)
static int fb(int x)
int ProcNumber
Definition procnumber.h:24
LockInstanceData * locks
Definition lock.h:318
int * waiter_pids
Definition lock.h:319
BlockedProcData * procs
Definition lock.h:317
LockInstanceData * locks
Definition lock.h:299
int nelements
Definition lock.h:298
LOCKMASK holdMask
Definition lock.h:286
PredicateLockData * predLockData
Definition lockfuncs.c:61
LockData * lockData
Definition lockfuncs.c:59
PREDICATELOCKTARGETTAG * locktags
SERIALIZABLEXACT * xacts
TupleDesc CreateTemplateTupleDesc(int natts)
Definition tupdesc.c:165
void TupleDescFinalize(TupleDesc tupdesc)
Definition tupdesc.c:508
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition tupdesc.c:897
static Datum TimestampTzGetDatum(TimestampTz X)
Definition timestamp.h:52