From 6613850df90f60a6e9daa0677bd81c64d5eb3107 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 8 Sep 2020 20:49:37 -0700
Subject: [PATCH v1 2/3] WIP: Treat BufferPin as a waiting condition in
 isolationtest.

---
 src/include/storage/procarray.h     |  1 +
 src/backend/storage/ipc/procarray.c | 24 ++++++++++++++++++++++++
 src/backend/utils/adt/lockfuncs.c   | 25 +++++++++++++++++++++++++
 3 files changed, 50 insertions(+)

diff --git a/src/include/storage/procarray.h b/src/include/storage/procarray.h
index ea8a876ca45..62ee6833787 100644
--- a/src/include/storage/procarray.h
+++ b/src/include/storage/procarray.h
@@ -66,6 +66,7 @@ extern PGPROC *BackendPidGetProc(int pid);
 extern PGPROC *BackendPidGetProcWithLock(int pid);
 extern int	BackendXidGetPid(TransactionId xid);
 extern bool IsBackendPid(int pid);
+extern uint32 BackendPidGetWaitEvent(int pid);
 
 extern VirtualTransactionId *GetCurrentVirtualXIDs(TransactionId limitXmin,
 												   bool excludeXmin0, bool allDbs, int excludeVacuum,
diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c
index 1c0cd6b2487..5fb67e0e217 100644
--- a/src/backend/storage/ipc/procarray.c
+++ b/src/backend/storage/ipc/procarray.c
@@ -3023,6 +3023,30 @@ BackendPidGetProcWithLock(int pid)
 	return result;
 }
 
+/*
+ * BackendPidGetWaitEvent -- return wait event of a backend
+ *
+ * This return 0 both if there is no backend with the passed PID and if the
+ * backend exists but is not currently waiting.
+ */
+uint32
+BackendPidGetWaitEvent(int pid)
+{
+	PGPROC	   *proc;
+	uint32		raw_wait_event = 0;
+
+	LWLockAcquire(ProcArrayLock, LW_SHARED);
+
+	proc = BackendPidGetProcWithLock(pid);
+
+	if (proc)
+		raw_wait_event = UINT32_ACCESS_ONCE(proc->wait_event_info);
+
+	LWLockRelease(ProcArrayLock);
+
+	return raw_wait_event;
+}
+
 /*
  * BackendXidGetPid -- get a backend's pid given its XID
  *
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index f592292d067..1f41a85d496 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -17,7 +17,9 @@
 #include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "miscadmin.h"
+#include "pgstat.h"
 #include "storage/predicate_internals.h"
+#include "storage/procarray.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 
@@ -601,6 +603,7 @@ pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
 	int			num_interesting_pids;
 	int			num_blocking_pids;
 	int			dummy;
+	uint32		raw_wait_event;
 	int			i,
 				j;
 
@@ -653,6 +656,28 @@ pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
 	if (GetSafeSnapshotBlockingPids(blocked_pid, &dummy, 1) > 0)
 		PG_RETURN_BOOL(true);
 
+	raw_wait_event = BackendPidGetWaitEvent(blocked_pid);
+
+	if (raw_wait_event != 0)
+	{
+		const char*	wait_event_type;
+		const char*	wait_event;
+
+		/*
+		 * FIXME: probably better to match on the integer value itself. But
+		 * currently the class / event mask is not exposed outside pgstat.c...
+		 */
+		wait_event_type = pgstat_get_wait_event_type(raw_wait_event);
+		wait_event = pgstat_get_wait_event(raw_wait_event);
+
+		if (wait_event_type != NULL && wait_event_type != NULL &&
+			strcmp(wait_event_type, "BufferPin") == 0 &&
+			strcmp(wait_event, "BufferPin") == 0)
+		{
+			PG_RETURN_BOOL(true);
+		}
+	}
+
 	PG_RETURN_BOOL(false);
 }
 
-- 
2.25.0.114.g5b0ca878e0

