Create waitfuncs.c for pg_isolation_test_session_is_blocked().
authorNoah Misch <[email protected]>
Fri, 28 Jun 2024 02:21:05 +0000 (19:21 -0700)
committerNoah Misch <[email protected]>
Fri, 28 Jun 2024 02:21:05 +0000 (19:21 -0700)
The next commit makes the function inspect an additional non-lock
contention source, so it no longer fits in lockfuncs.c.

Reviewed by Robert Haas.

Discussion: https://postgr.es/m/20240512232923[email protected]

src/backend/utils/adt/Makefile
src/backend/utils/adt/lockfuncs.c
src/backend/utils/adt/meson.build
src/backend/utils/adt/waitfuncs.c [new file with mode: 0644]

index 610ccf2f7994d05d5fa3285dde2d358cb592b5a8..edb09d4e35622346ecb943d82edaa2c173d12004 100644 (file)
@@ -116,6 +116,7 @@ OBJS = \
    varchar.o \
    varlena.o \
    version.o \
+   waitfuncs.o \
    windowfuncs.o \
    xid.o \
    xid8funcs.o \
index 13009cc3d0d142784436c26414cf37fd5381d315..e790f856ab37066d33145386f0a6c6ca530ea7e9 100644 (file)
@@ -13,7 +13,6 @@
 #include "postgres.h"
 
 #include "access/htup_details.h"
-#include "catalog/pg_type.h"
 #include "funcapi.h"
 #include "miscadmin.h"
 #include "storage/predicate_internals.h"
@@ -601,84 +600,6 @@ pg_safe_snapshot_blocking_pids(PG_FUNCTION_ARGS)
 }
 
 
-/*
- * pg_isolation_test_session_is_blocked - support function for isolationtester
- *
- * Check if specified PID is blocked by any of the PIDs listed in the second
- * argument.  Currently, this looks for blocking caused by waiting for
- * heavyweight locks or safe snapshots.  We ignore blockage caused by PIDs
- * not directly under the isolationtester's control, eg autovacuum.
- *
- * This is an undocumented function intended for use by the isolation tester,
- * and may change in future releases as required for testing purposes.
- */
-Datum
-pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
-{
-   int         blocked_pid = PG_GETARG_INT32(0);
-   ArrayType  *interesting_pids_a = PG_GETARG_ARRAYTYPE_P(1);
-   ArrayType  *blocking_pids_a;
-   int32      *interesting_pids;
-   int32      *blocking_pids;
-   int         num_interesting_pids;
-   int         num_blocking_pids;
-   int         dummy;
-   int         i,
-               j;
-
-   /* Validate the passed-in array */
-   Assert(ARR_ELEMTYPE(interesting_pids_a) == INT4OID);
-   if (array_contains_nulls(interesting_pids_a))
-       elog(ERROR, "array must not contain nulls");
-   interesting_pids = (int32 *) ARR_DATA_PTR(interesting_pids_a);
-   num_interesting_pids = ArrayGetNItems(ARR_NDIM(interesting_pids_a),
-                                         ARR_DIMS(interesting_pids_a));
-
-   /*
-    * Get the PIDs of all sessions blocking the given session's attempt to
-    * acquire heavyweight locks.
-    */
-   blocking_pids_a =
-       DatumGetArrayTypeP(DirectFunctionCall1(pg_blocking_pids, blocked_pid));
-
-   Assert(ARR_ELEMTYPE(blocking_pids_a) == INT4OID);
-   Assert(!array_contains_nulls(blocking_pids_a));
-   blocking_pids = (int32 *) ARR_DATA_PTR(blocking_pids_a);
-   num_blocking_pids = ArrayGetNItems(ARR_NDIM(blocking_pids_a),
-                                      ARR_DIMS(blocking_pids_a));
-
-   /*
-    * Check if any of these are in the list of interesting PIDs, that being
-    * the sessions that the isolation tester is running.  We don't use
-    * "arrayoverlaps" here, because it would lead to cache lookups and one of
-    * our goals is to run quickly with debug_discard_caches > 0.  We expect
-    * blocking_pids to be usually empty and otherwise a very small number in
-    * isolation tester cases, so make that the outer loop of a naive search
-    * for a match.
-    */
-   for (i = 0; i < num_blocking_pids; i++)
-       for (j = 0; j < num_interesting_pids; j++)
-       {
-           if (blocking_pids[i] == interesting_pids[j])
-               PG_RETURN_BOOL(true);
-       }
-
-   /*
-    * Check if blocked_pid is waiting for a safe snapshot.  We could in
-    * theory check the resulting array of blocker PIDs against the
-    * interesting PIDs list, but since there is no danger of autovacuum
-    * blocking GetSafeSnapshot there seems to be no point in expending cycles
-    * on allocating a buffer and searching for overlap; so it's presently
-    * sufficient for the isolation tester's purposes to use a single element
-    * buffer and check if the number of safe snapshot blockers is non-zero.
-    */
-   if (GetSafeSnapshotBlockingPids(blocked_pid, &dummy, 1) > 0)
-       PG_RETURN_BOOL(true);
-
-   PG_RETURN_BOOL(false);
-}
-
-
 /*
  * Functions for manipulating advisory locks
  *
index 48dbcf59a58ffb678187d0465b129184759906e6..8c6fc80c373b260ae76485c1ccfa868ec5ebb824 100644 (file)
@@ -103,6 +103,7 @@ backend_sources += files(
   'varchar.c',
   'varlena.c',
   'version.c',
+  'waitfuncs.c',
   'windowfuncs.c',
   'xid.c',
   'xid8funcs.c',
diff --git a/src/backend/utils/adt/waitfuncs.c b/src/backend/utils/adt/waitfuncs.c
new file mode 100644 (file)
index 0000000..d9c92c3
--- /dev/null
@@ -0,0 +1,96 @@
+/*-------------------------------------------------------------------------
+ *
+ * waitfuncs.c
+ *     Functions for SQL access to syntheses of multiple contention types.
+ *
+ * Copyright (c) 2002-2024, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *     src/backend/utils/adt/waitfuncs.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "catalog/pg_type.h"
+#include "storage/predicate_internals.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+
+
+/*
+ * pg_isolation_test_session_is_blocked - support function for isolationtester
+ *
+ * Check if specified PID is blocked by any of the PIDs listed in the second
+ * argument.  Currently, this looks for blocking caused by waiting for
+ * heavyweight locks or safe snapshots.  We ignore blockage caused by PIDs
+ * not directly under the isolationtester's control, eg autovacuum.
+ *
+ * This is an undocumented function intended for use by the isolation tester,
+ * and may change in future releases as required for testing purposes.
+ */
+Datum
+pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
+{
+   int         blocked_pid = PG_GETARG_INT32(0);
+   ArrayType  *interesting_pids_a = PG_GETARG_ARRAYTYPE_P(1);
+   ArrayType  *blocking_pids_a;
+   int32      *interesting_pids;
+   int32      *blocking_pids;
+   int         num_interesting_pids;
+   int         num_blocking_pids;
+   int         dummy;
+   int         i,
+               j;
+
+   /* Validate the passed-in array */
+   Assert(ARR_ELEMTYPE(interesting_pids_a) == INT4OID);
+   if (array_contains_nulls(interesting_pids_a))
+       elog(ERROR, "array must not contain nulls");
+   interesting_pids = (int32 *) ARR_DATA_PTR(interesting_pids_a);
+   num_interesting_pids = ArrayGetNItems(ARR_NDIM(interesting_pids_a),
+                                         ARR_DIMS(interesting_pids_a));
+
+   /*
+    * Get the PIDs of all sessions blocking the given session's attempt to
+    * acquire heavyweight locks.
+    */
+   blocking_pids_a =
+       DatumGetArrayTypeP(DirectFunctionCall1(pg_blocking_pids, blocked_pid));
+
+   Assert(ARR_ELEMTYPE(blocking_pids_a) == INT4OID);
+   Assert(!array_contains_nulls(blocking_pids_a));
+   blocking_pids = (int32 *) ARR_DATA_PTR(blocking_pids_a);
+   num_blocking_pids = ArrayGetNItems(ARR_NDIM(blocking_pids_a),
+                                      ARR_DIMS(blocking_pids_a));
+
+   /*
+    * Check if any of these are in the list of interesting PIDs, that being
+    * the sessions that the isolation tester is running.  We don't use
+    * "arrayoverlaps" here, because it would lead to cache lookups and one of
+    * our goals is to run quickly with debug_discard_caches > 0.  We expect
+    * blocking_pids to be usually empty and otherwise a very small number in
+    * isolation tester cases, so make that the outer loop of a naive search
+    * for a match.
+    */
+   for (i = 0; i < num_blocking_pids; i++)
+       for (j = 0; j < num_interesting_pids; j++)
+       {
+           if (blocking_pids[i] == interesting_pids[j])
+               PG_RETURN_BOOL(true);
+       }
+
+   /*
+    * Check if blocked_pid is waiting for a safe snapshot.  We could in
+    * theory check the resulting array of blocker PIDs against the
+    * interesting PIDs list, but since there is no danger of autovacuum
+    * blocking GetSafeSnapshot there seems to be no point in expending cycles
+    * on allocating a buffer and searching for overlap; so it's presently
+    * sufficient for the isolation tester's purposes to use a single element
+    * buffer and check if the number of safe snapshot blockers is non-zero.
+    */
+   if (GetSafeSnapshotBlockingPids(blocked_pid, &dummy, 1) > 0)
+       PG_RETURN_BOOL(true);
+
+   PG_RETURN_BOOL(false);
+}