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