PostgreSQL Source Code  git master
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-2019, 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 "access/xact.h"
17 #include "catalog/pg_type.h"
18 #include "funcapi.h"
19 #include "miscadmin.h"
21 #include "utils/array.h"
22 #include "utils/builtins.h"
23 
24 
25 /* This must match enum LockTagType! */
26 const char *const LockTagTypeNames[] = {
27  "relation",
28  "extend",
29  "page",
30  "tuple",
31  "transactionid",
32  "virtualxid",
33  "speculative token",
34  "object",
35  "userlock",
36  "advisory"
37 };
38 
39 /* This must match enum PredicateLockTargetType (predicate_internals.h) */
40 static const char *const PredicateLockTagTypeNames[] = {
41  "relation",
42  "page",
43  "tuple"
44 };
45 
46 /* Working status for pg_lock_status */
47 typedef struct
48 {
49  LockData *lockData; /* state data from lmgr */
50  int currIdx; /* current PROCLOCK index */
51  PredicateLockData *predLockData; /* state data for pred locks */
52  int predLockIdx; /* current index for pred lock */
54 
55 /* Number of columns in pg_locks output */
56 #define NUM_LOCK_STATUS_COLUMNS 15
57 
58 /*
59  * VXIDGetDatum - Construct a text representation of a VXID
60  *
61  * This is currently only used in pg_lock_status, so we put it here.
62  */
63 static Datum
65 {
66  /*
67  * The representation is "<bid>/<lxid>", decimal and unsigned decimal
68  * respectively. Note that elog.c also knows how to format a vxid.
69  */
70  char vxidstr[32];
71 
72  snprintf(vxidstr, sizeof(vxidstr), "%d/%u", bid, lxid);
73 
74  return CStringGetTextDatum(vxidstr);
75 }
76 
77 
78 /*
79  * pg_lock_status - produce a view with one row per held or awaited lock mode
80  */
81 Datum
83 {
84  FuncCallContext *funcctx;
85  PG_Lock_Status *mystatus;
86  LockData *lockData;
87  PredicateLockData *predLockData;
88 
89  if (SRF_IS_FIRSTCALL())
90  {
91  TupleDesc tupdesc;
92  MemoryContext oldcontext;
93 
94  /* create a function context for cross-call persistence */
95  funcctx = SRF_FIRSTCALL_INIT();
96 
97  /*
98  * switch to memory context appropriate for multiple function calls
99  */
100  oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
101 
102  /* build tupdesc for result tuples */
103  /* this had better match function's declaration in pg_proc.h */
105  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
106  TEXTOID, -1, 0);
107  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
108  OIDOID, -1, 0);
109  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "relation",
110  OIDOID, -1, 0);
111  TupleDescInitEntry(tupdesc, (AttrNumber) 4, "page",
112  INT4OID, -1, 0);
113  TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple",
114  INT2OID, -1, 0);
115  TupleDescInitEntry(tupdesc, (AttrNumber) 6, "virtualxid",
116  TEXTOID, -1, 0);
117  TupleDescInitEntry(tupdesc, (AttrNumber) 7, "transactionid",
118  XIDOID, -1, 0);
119  TupleDescInitEntry(tupdesc, (AttrNumber) 8, "classid",
120  OIDOID, -1, 0);
121  TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objid",
122  OIDOID, -1, 0);
123  TupleDescInitEntry(tupdesc, (AttrNumber) 10, "objsubid",
124  INT2OID, -1, 0);
125  TupleDescInitEntry(tupdesc, (AttrNumber) 11, "virtualtransaction",
126  TEXTOID, -1, 0);
127  TupleDescInitEntry(tupdesc, (AttrNumber) 12, "pid",
128  INT4OID, -1, 0);
129  TupleDescInitEntry(tupdesc, (AttrNumber) 13, "mode",
130  TEXTOID, -1, 0);
131  TupleDescInitEntry(tupdesc, (AttrNumber) 14, "granted",
132  BOOLOID, -1, 0);
133  TupleDescInitEntry(tupdesc, (AttrNumber) 15, "fastpath",
134  BOOLOID, -1, 0);
135 
136  funcctx->tuple_desc = BlessTupleDesc(tupdesc);
137 
138  /*
139  * Collect all the locking information that we will format and send
140  * out as a result set.
141  */
142  mystatus = (PG_Lock_Status *) palloc(sizeof(PG_Lock_Status));
143  funcctx->user_fctx = (void *) mystatus;
144 
145  mystatus->lockData = GetLockStatusData();
146  mystatus->currIdx = 0;
148  mystatus->predLockIdx = 0;
149 
150  MemoryContextSwitchTo(oldcontext);
151  }
152 
153  funcctx = SRF_PERCALL_SETUP();
154  mystatus = (PG_Lock_Status *) funcctx->user_fctx;
155  lockData = mystatus->lockData;
156 
157  while (mystatus->currIdx < lockData->nelements)
158  {
159  bool granted;
160  LOCKMODE mode = 0;
161  const char *locktypename;
162  char tnbuf[32];
164  bool nulls[NUM_LOCK_STATUS_COLUMNS];
165  HeapTuple tuple;
166  Datum result;
167  LockInstanceData *instance;
168 
169  instance = &(lockData->locks[mystatus->currIdx]);
170 
171  /*
172  * Look to see if there are any held lock modes in this PROCLOCK. If
173  * so, report, and destructively modify lockData so we don't report
174  * again.
175  */
176  granted = false;
177  if (instance->holdMask)
178  {
179  for (mode = 0; mode < MAX_LOCKMODES; mode++)
180  {
181  if (instance->holdMask & LOCKBIT_ON(mode))
182  {
183  granted = true;
184  instance->holdMask &= LOCKBIT_OFF(mode);
185  break;
186  }
187  }
188  }
189 
190  /*
191  * If no (more) held modes to report, see if PROC is waiting for a
192  * lock on this lock.
193  */
194  if (!granted)
195  {
196  if (instance->waitLockMode != NoLock)
197  {
198  /* Yes, so report it with proper mode */
199  mode = instance->waitLockMode;
200 
201  /*
202  * We are now done with this PROCLOCK, so advance pointer to
203  * continue with next one on next call.
204  */
205  mystatus->currIdx++;
206  }
207  else
208  {
209  /*
210  * Okay, we've displayed all the locks associated with this
211  * PROCLOCK, proceed to the next one.
212  */
213  mystatus->currIdx++;
214  continue;
215  }
216  }
217 
218  /*
219  * Form tuple with appropriate data.
220  */
221  MemSet(values, 0, sizeof(values));
222  MemSet(nulls, false, sizeof(nulls));
223 
224  if (instance->locktag.locktag_type <= LOCKTAG_LAST_TYPE)
225  locktypename = LockTagTypeNames[instance->locktag.locktag_type];
226  else
227  {
228  snprintf(tnbuf, sizeof(tnbuf), "unknown %d",
229  (int) instance->locktag.locktag_type);
230  locktypename = tnbuf;
231  }
232  values[0] = CStringGetTextDatum(locktypename);
233 
234  switch ((LockTagType) instance->locktag.locktag_type)
235  {
236  case LOCKTAG_RELATION:
238  values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
239  values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
240  nulls[3] = true;
241  nulls[4] = true;
242  nulls[5] = true;
243  nulls[6] = true;
244  nulls[7] = true;
245  nulls[8] = true;
246  nulls[9] = true;
247  break;
248  case LOCKTAG_PAGE:
249  values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
250  values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
251  values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
252  nulls[4] = true;
253  nulls[5] = true;
254  nulls[6] = true;
255  nulls[7] = true;
256  nulls[8] = true;
257  nulls[9] = true;
258  break;
259  case LOCKTAG_TUPLE:
260  values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
261  values[2] = ObjectIdGetDatum(instance->locktag.locktag_field2);
262  values[3] = UInt32GetDatum(instance->locktag.locktag_field3);
263  values[4] = UInt16GetDatum(instance->locktag.locktag_field4);
264  nulls[5] = true;
265  nulls[6] = true;
266  nulls[7] = true;
267  nulls[8] = true;
268  nulls[9] = true;
269  break;
270  case LOCKTAG_TRANSACTION:
271  values[6] =
273  nulls[1] = true;
274  nulls[2] = true;
275  nulls[3] = true;
276  nulls[4] = true;
277  nulls[5] = true;
278  nulls[7] = true;
279  nulls[8] = true;
280  nulls[9] = true;
281  break;
283  values[5] = VXIDGetDatum(instance->locktag.locktag_field1,
284  instance->locktag.locktag_field2);
285  nulls[1] = true;
286  nulls[2] = true;
287  nulls[3] = true;
288  nulls[4] = true;
289  nulls[6] = true;
290  nulls[7] = true;
291  nulls[8] = true;
292  nulls[9] = true;
293  break;
294  case LOCKTAG_OBJECT:
295  case LOCKTAG_USERLOCK:
296  case LOCKTAG_ADVISORY:
297  default: /* treat unknown locktags like OBJECT */
298  values[1] = ObjectIdGetDatum(instance->locktag.locktag_field1);
299  values[7] = ObjectIdGetDatum(instance->locktag.locktag_field2);
300  values[8] = ObjectIdGetDatum(instance->locktag.locktag_field3);
301  values[9] = Int16GetDatum(instance->locktag.locktag_field4);
302  nulls[2] = true;
303  nulls[3] = true;
304  nulls[4] = true;
305  nulls[5] = true;
306  nulls[6] = true;
307  break;
308  }
309 
310  values[10] = VXIDGetDatum(instance->backend, instance->lxid);
311  if (instance->pid != 0)
312  values[11] = Int32GetDatum(instance->pid);
313  else
314  nulls[11] = true;
315  values[12] = CStringGetTextDatum(GetLockmodeName(instance->locktag.locktag_lockmethodid, mode));
316  values[13] = BoolGetDatum(granted);
317  values[14] = BoolGetDatum(instance->fastpath);
318 
319  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
320  result = HeapTupleGetDatum(tuple);
321  SRF_RETURN_NEXT(funcctx, result);
322  }
323 
324  /*
325  * Have returned all regular locks. Now start on the SIREAD predicate
326  * locks.
327  */
328  predLockData = mystatus->predLockData;
329  if (mystatus->predLockIdx < predLockData->nelements)
330  {
331  PredicateLockTargetType lockType;
332 
333  PREDICATELOCKTARGETTAG *predTag = &(predLockData->locktags[mystatus->predLockIdx]);
334  SERIALIZABLEXACT *xact = &(predLockData->xacts[mystatus->predLockIdx]);
336  bool nulls[NUM_LOCK_STATUS_COLUMNS];
337  HeapTuple tuple;
338  Datum result;
339 
340  mystatus->predLockIdx++;
341 
342  /*
343  * Form tuple with appropriate data.
344  */
345  MemSet(values, 0, sizeof(values));
346  MemSet(nulls, false, sizeof(nulls));
347 
348  /* lock type */
349  lockType = GET_PREDICATELOCKTARGETTAG_TYPE(*predTag);
350 
351  values[0] = CStringGetTextDatum(PredicateLockTagTypeNames[lockType]);
352 
353  /* lock target */
354  values[1] = GET_PREDICATELOCKTARGETTAG_DB(*predTag);
355  values[2] = GET_PREDICATELOCKTARGETTAG_RELATION(*predTag);
356  if (lockType == PREDLOCKTAG_TUPLE)
357  values[4] = GET_PREDICATELOCKTARGETTAG_OFFSET(*predTag);
358  else
359  nulls[4] = true;
360  if ((lockType == PREDLOCKTAG_TUPLE) ||
361  (lockType == PREDLOCKTAG_PAGE))
362  values[3] = GET_PREDICATELOCKTARGETTAG_PAGE(*predTag);
363  else
364  nulls[3] = true;
365 
366  /* these fields are targets for other types of locks */
367  nulls[5] = true; /* virtualxid */
368  nulls[6] = true; /* transactionid */
369  nulls[7] = true; /* classid */
370  nulls[8] = true; /* objid */
371  nulls[9] = true; /* objsubid */
372 
373  /* lock holder */
374  values[10] = VXIDGetDatum(xact->vxid.backendId,
375  xact->vxid.localTransactionId);
376  if (xact->pid != 0)
377  values[11] = Int32GetDatum(xact->pid);
378  else
379  nulls[11] = true;
380 
381  /*
382  * Lock mode. Currently all predicate locks are SIReadLocks, which are
383  * always held (never waiting) and have no fast path
384  */
385  values[12] = CStringGetTextDatum("SIReadLock");
386  values[13] = BoolGetDatum(true);
387  values[14] = BoolGetDatum(false);
388 
389  tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
390  result = HeapTupleGetDatum(tuple);
391  SRF_RETURN_NEXT(funcctx, result);
392  }
393 
394  SRF_RETURN_DONE(funcctx);
395 }
396 
397 
398 /*
399  * pg_blocking_pids - produce an array of the PIDs blocking given PID
400  *
401  * The reported PIDs are those that hold a lock conflicting with blocked_pid's
402  * current request (hard block), or are requesting such a lock and are ahead
403  * of blocked_pid in the lock's wait queue (soft block).
404  *
405  * In parallel-query cases, we report all PIDs blocking any member of the
406  * given PID's lock group, and the reported PIDs are those of the blocking
407  * PIDs' lock group leaders. This allows callers to compare the result to
408  * lists of clients' pg_backend_pid() results even during a parallel query.
409  *
410  * Parallel query makes it possible for there to be duplicate PIDs in the
411  * result (either because multiple waiters are blocked by same PID, or
412  * because multiple blockers have same group leader PID). We do not bother
413  * to eliminate such duplicates from the result.
414  *
415  * We need not consider predicate locks here, since those don't block anything.
416  */
417 Datum
419 {
420  int blocked_pid = PG_GETARG_INT32(0);
421  Datum *arrayelems;
422  int narrayelems;
423  BlockedProcsData *lockData; /* state data from lmgr */
424  int i,
425  j;
426 
427  /* Collect a snapshot of lock manager state */
428  lockData = GetBlockerStatusData(blocked_pid);
429 
430  /* We can't need more output entries than there are reported PROCLOCKs */
431  arrayelems = (Datum *) palloc(lockData->nlocks * sizeof(Datum));
432  narrayelems = 0;
433 
434  /* For each blocked proc in the lock group ... */
435  for (i = 0; i < lockData->nprocs; i++)
436  {
437  BlockedProcData *bproc = &lockData->procs[i];
438  LockInstanceData *instances = &lockData->locks[bproc->first_lock];
439  int *preceding_waiters = &lockData->waiter_pids[bproc->first_waiter];
440  LockInstanceData *blocked_instance;
441  LockMethod lockMethodTable;
442  int conflictMask;
443 
444  /*
445  * Locate the blocked proc's own entry in the LockInstanceData array.
446  * There should be exactly one matching entry.
447  */
448  blocked_instance = NULL;
449  for (j = 0; j < bproc->num_locks; j++)
450  {
451  LockInstanceData *instance = &(instances[j]);
452 
453  if (instance->pid == bproc->pid)
454  {
455  Assert(blocked_instance == NULL);
456  blocked_instance = instance;
457  }
458  }
459  Assert(blocked_instance != NULL);
460 
461  lockMethodTable = GetLockTagsMethodTable(&(blocked_instance->locktag));
462  conflictMask = lockMethodTable->conflictTab[blocked_instance->waitLockMode];
463 
464  /* Now scan the PROCLOCK data for conflicting procs */
465  for (j = 0; j < bproc->num_locks; j++)
466  {
467  LockInstanceData *instance = &(instances[j]);
468 
469  /* A proc never blocks itself, so ignore that entry */
470  if (instance == blocked_instance)
471  continue;
472  /* Members of same lock group never block each other, either */
473  if (instance->leaderPid == blocked_instance->leaderPid)
474  continue;
475 
476  if (conflictMask & instance->holdMask)
477  {
478  /* hard block: blocked by lock already held by this entry */
479  }
480  else if (instance->waitLockMode != NoLock &&
481  (conflictMask & LOCKBIT_ON(instance->waitLockMode)))
482  {
483  /* conflict in lock requests; who's in front in wait queue? */
484  bool ahead = false;
485  int k;
486 
487  for (k = 0; k < bproc->num_waiters; k++)
488  {
489  if (preceding_waiters[k] == instance->pid)
490  {
491  /* soft block: this entry is ahead of blocked proc */
492  ahead = true;
493  break;
494  }
495  }
496  if (!ahead)
497  continue; /* not blocked by this entry */
498  }
499  else
500  {
501  /* not blocked by this entry */
502  continue;
503  }
504 
505  /* blocked by this entry, so emit a record */
506  arrayelems[narrayelems++] = Int32GetDatum(instance->leaderPid);
507  }
508  }
509 
510  /* Assert we didn't overrun arrayelems[] */
511  Assert(narrayelems <= lockData->nlocks);
512 
513  /* Construct array, using hardwired knowledge about int4 type */
514  PG_RETURN_ARRAYTYPE_P(construct_array(arrayelems, narrayelems,
515  INT4OID,
516  sizeof(int32), true, 'i'));
517 }
518 
519 
520 /*
521  * pg_safe_snapshot_blocking_pids - produce an array of the PIDs blocking
522  * given PID from getting a safe snapshot
523  *
524  * XXX this does not consider parallel-query cases; not clear how big a
525  * problem that is in practice
526  */
527 Datum
529 {
530  int blocked_pid = PG_GETARG_INT32(0);
531  int *blockers;
532  int num_blockers;
533  Datum *blocker_datums;
534 
535  /* A buffer big enough for any possible blocker list without truncation */
536  blockers = (int *) palloc(MaxBackends * sizeof(int));
537 
538  /* Collect a snapshot of processes waited for by GetSafeSnapshot */
539  num_blockers =
540  GetSafeSnapshotBlockingPids(blocked_pid, blockers, MaxBackends);
541 
542  /* Convert int array to Datum array */
543  if (num_blockers > 0)
544  {
545  int i;
546 
547  blocker_datums = (Datum *) palloc(num_blockers * sizeof(Datum));
548  for (i = 0; i < num_blockers; ++i)
549  blocker_datums[i] = Int32GetDatum(blockers[i]);
550  }
551  else
552  blocker_datums = NULL;
553 
554  /* Construct array, using hardwired knowledge about int4 type */
555  PG_RETURN_ARRAYTYPE_P(construct_array(blocker_datums, num_blockers,
556  INT4OID,
557  sizeof(int32), true, 'i'));
558 }
559 
560 
561 /*
562  * pg_isolation_test_session_is_blocked - support function for isolationtester
563  *
564  * Check if specified PID is blocked by any of the PIDs listed in the second
565  * argument. Currently, this looks for blocking caused by waiting for
566  * heavyweight locks or safe snapshots. We ignore blockage caused by PIDs
567  * not directly under the isolationtester's control, eg autovacuum.
568  *
569  * This is an undocumented function intended for use by the isolation tester,
570  * and may change in future releases as required for testing purposes.
571  */
572 Datum
574 {
575  int blocked_pid = PG_GETARG_INT32(0);
576  ArrayType *interesting_pids_a = PG_GETARG_ARRAYTYPE_P(1);
577  ArrayType *blocking_pids_a;
578  int32 *interesting_pids;
579  int32 *blocking_pids;
580  int num_interesting_pids;
581  int num_blocking_pids;
582  int dummy;
583  int i,
584  j;
585 
586  /* Validate the passed-in array */
587  Assert(ARR_ELEMTYPE(interesting_pids_a) == INT4OID);
588  if (array_contains_nulls(interesting_pids_a))
589  elog(ERROR, "array must not contain nulls");
590  interesting_pids = (int32 *) ARR_DATA_PTR(interesting_pids_a);
591  num_interesting_pids = ArrayGetNItems(ARR_NDIM(interesting_pids_a),
592  ARR_DIMS(interesting_pids_a));
593 
594  /*
595  * Get the PIDs of all sessions blocking the given session's attempt to
596  * acquire heavyweight locks.
597  */
598  blocking_pids_a =
600 
601  Assert(ARR_ELEMTYPE(blocking_pids_a) == INT4OID);
602  Assert(!array_contains_nulls(blocking_pids_a));
603  blocking_pids = (int32 *) ARR_DATA_PTR(blocking_pids_a);
604  num_blocking_pids = ArrayGetNItems(ARR_NDIM(blocking_pids_a),
605  ARR_DIMS(blocking_pids_a));
606 
607  /*
608  * Check if any of these are in the list of interesting PIDs, that being
609  * the sessions that the isolation tester is running. We don't use
610  * "arrayoverlaps" here, because it would lead to cache lookups and one of
611  * our goals is to run quickly under CLOBBER_CACHE_ALWAYS. We expect
612  * blocking_pids to be usually empty and otherwise a very small number in
613  * isolation tester cases, so make that the outer loop of a naive search
614  * for a match.
615  */
616  for (i = 0; i < num_blocking_pids; i++)
617  for (j = 0; j < num_interesting_pids; j++)
618  {
619  if (blocking_pids[i] == interesting_pids[j])
620  PG_RETURN_BOOL(true);
621  }
622 
623  /*
624  * Check if blocked_pid is waiting for a safe snapshot. We could in
625  * theory check the resulting array of blocker PIDs against the
626  * interesting PIDs whitelist, but since there is no danger of autovacuum
627  * blocking GetSafeSnapshot there seems to be no point in expending cycles
628  * on allocating a buffer and searching for overlap; so it's presently
629  * sufficient for the isolation tester's purposes to use a single element
630  * buffer and check if the number of safe snapshot blockers is non-zero.
631  */
632  if (GetSafeSnapshotBlockingPids(blocked_pid, &dummy, 1) > 0)
633  PG_RETURN_BOOL(true);
634 
635  PG_RETURN_BOOL(false);
636 }
637 
638 
639 /*
640  * Functions for manipulating advisory locks
641  *
642  * We make use of the locktag fields as follows:
643  *
644  * field1: MyDatabaseId ... ensures locks are local to each database
645  * field2: first of 2 int4 keys, or high-order half of an int8 key
646  * field3: second of 2 int4 keys, or low-order half of an int8 key
647  * field4: 1 if using an int8 key, 2 if using 2 int4 keys
648  */
649 #define SET_LOCKTAG_INT64(tag, key64) \
650  SET_LOCKTAG_ADVISORY(tag, \
651  MyDatabaseId, \
652  (uint32) ((key64) >> 32), \
653  (uint32) (key64), \
654  1)
655 #define SET_LOCKTAG_INT32(tag, key1, key2) \
656  SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key1, key2, 2)
657 
658 /*
659  * pg_advisory_lock(int8) - acquire exclusive lock on an int8 key
660  */
661 Datum
663 {
664  int64 key = PG_GETARG_INT64(0);
665  LOCKTAG tag;
666 
667  SET_LOCKTAG_INT64(tag, key);
668 
669  (void) LockAcquire(&tag, ExclusiveLock, true, false);
670 
671  PG_RETURN_VOID();
672 }
673 
674 /*
675  * pg_advisory_xact_lock(int8) - acquire xact scoped
676  * exclusive lock on an int8 key
677  */
678 Datum
680 {
681  int64 key = PG_GETARG_INT64(0);
682  LOCKTAG tag;
683 
684  SET_LOCKTAG_INT64(tag, key);
685 
686  (void) LockAcquire(&tag, ExclusiveLock, false, false);
687 
688  PG_RETURN_VOID();
689 }
690 
691 /*
692  * pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
693  */
694 Datum
696 {
697  int64 key = PG_GETARG_INT64(0);
698  LOCKTAG tag;
699 
700  SET_LOCKTAG_INT64(tag, key);
701 
702  (void) LockAcquire(&tag, ShareLock, true, false);
703 
704  PG_RETURN_VOID();
705 }
706 
707 /*
708  * pg_advisory_xact_lock_shared(int8) - acquire xact scoped
709  * share lock on an int8 key
710  */
711 Datum
713 {
714  int64 key = PG_GETARG_INT64(0);
715  LOCKTAG tag;
716 
717  SET_LOCKTAG_INT64(tag, key);
718 
719  (void) LockAcquire(&tag, ShareLock, false, false);
720 
721  PG_RETURN_VOID();
722 }
723 
724 /*
725  * pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
726  *
727  * Returns true if successful, false if lock not available
728  */
729 Datum
731 {
732  int64 key = PG_GETARG_INT64(0);
733  LOCKTAG tag;
734  LockAcquireResult res;
735 
736  SET_LOCKTAG_INT64(tag, key);
737 
738  res = LockAcquire(&tag, ExclusiveLock, true, true);
739 
741 }
742 
743 /*
744  * pg_try_advisory_xact_lock(int8) - acquire xact scoped
745  * exclusive lock on an int8 key, no wait
746  *
747  * Returns true if successful, false if lock not available
748  */
749 Datum
751 {
752  int64 key = PG_GETARG_INT64(0);
753  LOCKTAG tag;
754  LockAcquireResult res;
755 
756  SET_LOCKTAG_INT64(tag, key);
757 
758  res = LockAcquire(&tag, ExclusiveLock, false, true);
759 
761 }
762 
763 /*
764  * pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
765  *
766  * Returns true if successful, false if lock not available
767  */
768 Datum
770 {
771  int64 key = PG_GETARG_INT64(0);
772  LOCKTAG tag;
773  LockAcquireResult res;
774 
775  SET_LOCKTAG_INT64(tag, key);
776 
777  res = LockAcquire(&tag, ShareLock, true, true);
778 
780 }
781 
782 /*
783  * pg_try_advisory_xact_lock_shared(int8) - acquire xact scoped
784  * share lock on an int8 key, no wait
785  *
786  * Returns true if successful, false if lock not available
787  */
788 Datum
790 {
791  int64 key = PG_GETARG_INT64(0);
792  LOCKTAG tag;
793  LockAcquireResult res;
794 
795  SET_LOCKTAG_INT64(tag, key);
796 
797  res = LockAcquire(&tag, ShareLock, false, true);
798 
800 }
801 
802 /*
803  * pg_advisory_unlock(int8) - release exclusive lock on an int8 key
804  *
805  * Returns true if successful, false if lock was not held
806 */
807 Datum
809 {
810  int64 key = PG_GETARG_INT64(0);
811  LOCKTAG tag;
812  bool res;
813 
814  SET_LOCKTAG_INT64(tag, key);
815 
816  res = LockRelease(&tag, ExclusiveLock, true);
817 
818  PG_RETURN_BOOL(res);
819 }
820 
821 /*
822  * pg_advisory_unlock_shared(int8) - release share lock on an int8 key
823  *
824  * Returns true if successful, false if lock was not held
825  */
826 Datum
828 {
829  int64 key = PG_GETARG_INT64(0);
830  LOCKTAG tag;
831  bool res;
832 
833  SET_LOCKTAG_INT64(tag, key);
834 
835  res = LockRelease(&tag, ShareLock, true);
836 
837  PG_RETURN_BOOL(res);
838 }
839 
840 /*
841  * pg_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys
842  */
843 Datum
845 {
846  int32 key1 = PG_GETARG_INT32(0);
847  int32 key2 = PG_GETARG_INT32(1);
848  LOCKTAG tag;
849 
850  SET_LOCKTAG_INT32(tag, key1, key2);
851 
852  (void) LockAcquire(&tag, ExclusiveLock, true, false);
853 
854  PG_RETURN_VOID();
855 }
856 
857 /*
858  * pg_advisory_xact_lock(int4, int4) - acquire xact scoped
859  * exclusive lock on 2 int4 keys
860  */
861 Datum
863 {
864  int32 key1 = PG_GETARG_INT32(0);
865  int32 key2 = PG_GETARG_INT32(1);
866  LOCKTAG tag;
867 
868  SET_LOCKTAG_INT32(tag, key1, key2);
869 
870  (void) LockAcquire(&tag, ExclusiveLock, false, false);
871 
872  PG_RETURN_VOID();
873 }
874 
875 /*
876  * pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
877  */
878 Datum
880 {
881  int32 key1 = PG_GETARG_INT32(0);
882  int32 key2 = PG_GETARG_INT32(1);
883  LOCKTAG tag;
884 
885  SET_LOCKTAG_INT32(tag, key1, key2);
886 
887  (void) LockAcquire(&tag, ShareLock, true, false);
888 
889  PG_RETURN_VOID();
890 }
891 
892 /*
893  * pg_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
894  * share lock on 2 int4 keys
895  */
896 Datum
898 {
899  int32 key1 = PG_GETARG_INT32(0);
900  int32 key2 = PG_GETARG_INT32(1);
901  LOCKTAG tag;
902 
903  SET_LOCKTAG_INT32(tag, key1, key2);
904 
905  (void) LockAcquire(&tag, ShareLock, false, false);
906 
907  PG_RETURN_VOID();
908 }
909 
910 /*
911  * pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
912  *
913  * Returns true if successful, false if lock not available
914  */
915 Datum
917 {
918  int32 key1 = PG_GETARG_INT32(0);
919  int32 key2 = PG_GETARG_INT32(1);
920  LOCKTAG tag;
921  LockAcquireResult res;
922 
923  SET_LOCKTAG_INT32(tag, key1, key2);
924 
925  res = LockAcquire(&tag, ExclusiveLock, true, true);
926 
928 }
929 
930 /*
931  * pg_try_advisory_xact_lock(int4, int4) - acquire xact scoped
932  * exclusive lock on 2 int4 keys, no wait
933  *
934  * Returns true if successful, false if lock not available
935  */
936 Datum
938 {
939  int32 key1 = PG_GETARG_INT32(0);
940  int32 key2 = PG_GETARG_INT32(1);
941  LOCKTAG tag;
942  LockAcquireResult res;
943 
944  SET_LOCKTAG_INT32(tag, key1, key2);
945 
946  res = LockAcquire(&tag, ExclusiveLock, false, true);
947 
949 }
950 
951 /*
952  * pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
953  *
954  * Returns true if successful, false if lock not available
955  */
956 Datum
958 {
959  int32 key1 = PG_GETARG_INT32(0);
960  int32 key2 = PG_GETARG_INT32(1);
961  LOCKTAG tag;
962  LockAcquireResult res;
963 
964  SET_LOCKTAG_INT32(tag, key1, key2);
965 
966  res = LockAcquire(&tag, ShareLock, true, true);
967 
969 }
970 
971 /*
972  * pg_try_advisory_xact_lock_shared(int4, int4) - acquire xact scoped
973  * share lock on 2 int4 keys, no wait
974  *
975  * Returns true if successful, false if lock not available
976  */
977 Datum
979 {
980  int32 key1 = PG_GETARG_INT32(0);
981  int32 key2 = PG_GETARG_INT32(1);
982  LOCKTAG tag;
983  LockAcquireResult res;
984 
985  SET_LOCKTAG_INT32(tag, key1, key2);
986 
987  res = LockAcquire(&tag, ShareLock, false, true);
988 
990 }
991 
992 /*
993  * pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
994  *
995  * Returns true if successful, false if lock was not held
996 */
997 Datum
999 {
1000  int32 key1 = PG_GETARG_INT32(0);
1001  int32 key2 = PG_GETARG_INT32(1);
1002  LOCKTAG tag;
1003  bool res;
1004 
1005  SET_LOCKTAG_INT32(tag, key1, key2);
1006 
1007  res = LockRelease(&tag, ExclusiveLock, true);
1008 
1009  PG_RETURN_BOOL(res);
1010 }
1011 
1012 /*
1013  * pg_advisory_unlock_shared(int4, int4) - release share lock on 2 int4 keys
1014  *
1015  * Returns true if successful, false if lock was not held
1016  */
1017 Datum
1019 {
1020  int32 key1 = PG_GETARG_INT32(0);
1021  int32 key2 = PG_GETARG_INT32(1);
1022  LOCKTAG tag;
1023  bool res;
1024 
1025  SET_LOCKTAG_INT32(tag, key1, key2);
1026 
1027  res = LockRelease(&tag, ShareLock, true);
1028 
1029  PG_RETURN_BOOL(res);
1030 }
1031 
1032 /*
1033  * pg_advisory_unlock_all() - release all advisory locks
1034  */
1035 Datum
1037 {
1039 
1040  PG_RETURN_VOID();
1041 }
#define GET_PREDICATELOCKTARGETTAG_RELATION(locktag)
#define GET_PREDICATELOCKTARGETTAG_PAGE(locktag)
static PgChecksumMode mode
Definition: pg_checksums.c:61
#define PG_GETARG_INT32(n)
Definition: fmgr.h:264
int * waiter_pids
Definition: lock.h:465
Datum pg_try_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:789
LockAcquireResult LockAcquire(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock, bool dontWait)
Definition: lock.c:708
const char * GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode)
Definition: lock.c:3925
PredicateLockTargetType
LockInstanceData * locks
Definition: lock.h:445
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:44
BlockedProcsData * GetBlockerStatusData(int blocked_pid)
Definition: lock.c:3662
Datum pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:573
int LOCKMODE
Definition: lockdefs.h:26
int first_lock
Definition: lock.h:453
#define SET_LOCKTAG_INT32(tag, key1, key2)
Definition: lockfuncs.c:655
#define ExclusiveLock
Definition: lockdefs.h:44
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:283
int num_waiters
Definition: lock.h:458
bool fastpath
Definition: lock.h:439
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
Datum pg_try_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:937
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define Int16GetDatum(X)
Definition: postgres.h:451
Datum pg_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:879
ArrayType * construct_array(Datum *elems, int nelems, Oid elmtype, int elmlen, bool elmbyval, char elmalign)
Definition: arrayfuncs.c:3291
Definition: lock.h:164
const LOCKMASK * conflictTab
Definition: lock.h:114
#define MemSet(start, val, len)
Definition: c.h:955
SERIALIZABLEXACT * xacts
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:617
BlockedProcData * procs
Definition: lock.h:463
Definition: lock.h:442
LocalTransactionId localTransactionId
Definition: lock.h:66
#define NUM_LOCK_STATUS_COLUMNS
Definition: lockfuncs.c:56
LOCKTAG locktag
Definition: lock.h:432
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:287
LOCKMODE waitLockMode
Definition: lock.h:434
PredicateLockData * GetPredicateLockStatusData(void)
Definition: predicate.c:1376
TupleDesc tuple_desc
Definition: funcapi.h:113
int num_locks
Definition: lock.h:454
signed int int32
Definition: c.h:346
uint16 locktag_field4
Definition: lock.h:169
int leaderPid
Definition: lock.h:438
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:289
#define LOCKBIT_OFF(lockmode)
Definition: lock.h:88
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:251
#define GET_PREDICATELOCKTARGETTAG_OFFSET(locktag)
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
Datum pg_blocking_pids(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:418
#define ARR_DIMS(a)
Definition: array.h:282
Datum pg_advisory_lock_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:844
Datum pg_try_advisory_lock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:730
int MaxBackends
Definition: globals.c:135
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2048
Datum pg_try_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:750
#define ARR_DATA_PTR(a)
Definition: array.h:310
LockData * GetLockStatusData(void)
Definition: lock.c:3478
VirtualTransactionId vxid
#define NoLock
Definition: lockdefs.h:34
#define GET_PREDICATELOCKTARGETTAG_TYPE(locktag)
#define USER_LOCKMETHOD
Definition: lock.h:129
Datum pg_try_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:957
uint32 locktag_field2
Definition: lock.h:167
#define GET_PREDICATELOCKTARGETTAG_DB(locktag)
#define UInt32GetDatum(X)
Definition: postgres.h:493
uint32 LocalTransactionId
Definition: c.h:509
Datum pg_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:897
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:603
Datum pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:695
#define PG_RETURN_ARRAYTYPE_P(x)
Definition: array.h:253
Datum pg_advisory_unlock_all(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:1036
PREDICATELOCKTARGETTAG * locktags
static const char *const PredicateLockTagTypeNames[]
Definition: lockfuncs.c:40
int nelements
Definition: lock.h:444
#define TransactionIdGetDatum(X)
Definition: postgres.h:521
#define MAX_LOCKMODES
Definition: lock.h:85
Datum pg_try_advisory_lock_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:916
Datum pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:528
Datum pg_try_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:769
LockInstanceData * locks
Definition: lock.h:464
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:349
uintptr_t Datum
Definition: postgres.h:367
BackendId backend
Definition: lock.h:435
int BackendId
Definition: backendid.h:21
#define BoolGetDatum(X)
Definition: postgres.h:402
LockMethod GetLockTagsMethodTable(const LOCKTAG *locktag)
Definition: lock.c:472
int first_waiter
Definition: lock.h:457
#define PG_RETURN_VOID()
Definition: fmgr.h:339
#define LOCKTAG_LAST_TYPE
Definition: lock.h:152
uint8 locktag_type
Definition: lock.h:170
LocalTransactionId lxid
Definition: lock.h:436
#define Assert(condition)
Definition: c.h:732
Datum pg_advisory_unlock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:808
BackendId backendId
Definition: lock.h:65
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:102
void LockReleaseSession(LOCKMETHODID lockmethodid)
Definition: lock.c:2363
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:221
Datum pg_advisory_xact_lock_shared_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:712
#define ARR_NDIM(a)
Definition: array.h:278
LOCKMASK holdMask
Definition: lock.h:433
uint8 locktag_lockmethodid
Definition: lock.h:171
#define LOCKBIT_ON(lockmode)
Definition: lock.h:87
static Datum values[MAXATTR]
Definition: bootstrap.c:167
PredicateLockData * predLockData
Definition: lockfuncs.c:51
Datum pg_advisory_unlock_shared_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:827
#define Int32GetDatum(X)
Definition: postgres.h:479
void * user_fctx
Definition: funcapi.h:83
void * palloc(Size size)
Definition: mcxt.c:949
LockAcquireResult
Definition: lock.h:476
Datum pg_lock_status(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:82
#define elog(elevel,...)
Definition: elog.h:226
#define ShareLock
Definition: lockdefs.h:41
int i
bool LockRelease(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
Definition: lock.c:1884
int GetSafeSnapshotBlockingPids(int blocked_pid, int *output, int output_size)
Definition: predicate.c:1561
LockData * lockData
Definition: lockfuncs.c:49
#define CStringGetTextDatum(s)
Definition: builtins.h:83
const char *const LockTagTypeNames[]
Definition: lockfuncs.c:26
LockTagType
Definition: lock.h:138
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188
Datum pg_advisory_xact_lock_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:862
Datum pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:1018
Datum pg_advisory_xact_lock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:679
#define SET_LOCKTAG_INT64(tag, key64)
Definition: lockfuncs.c:649
uint32 locktag_field1
Definition: lock.h:166
bool array_contains_nulls(ArrayType *array)
Definition: arrayfuncs.c:3528
#define PG_GETARG_INT64(n)
Definition: fmgr.h:277
#define snprintf
Definition: port.h:192
#define ARR_ELEMTYPE(a)
Definition: array.h:280
#define UInt16GetDatum(X)
Definition: postgres.h:465
int16 AttrNumber
Definition: attnum.h:21
uint32 locktag_field3
Definition: lock.h:168
static Datum VXIDGetDatum(BackendId bid, LocalTransactionId lxid)
Definition: lockfuncs.c:64
Datum pg_advisory_lock_int8(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:662
Datum pg_advisory_unlock_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:998
Datum pg_try_advisory_xact_lock_shared_int4(PG_FUNCTION_ARGS)
Definition: lockfuncs.c:978
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:307
#define DatumGetArrayTypeP(X)
Definition: array.h:249
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:285