PostgreSQL Source Code
git master
waitfuncs.c
Go to the documentation of this file.
1
/*-------------------------------------------------------------------------
2
*
3
* waitfuncs.c
4
* Functions for SQL access to syntheses of multiple contention types.
5
*
6
* Copyright (c) 2002-2025, PostgreSQL Global Development Group
7
*
8
* IDENTIFICATION
9
* src/backend/utils/adt/waitfuncs.c
10
*
11
*-------------------------------------------------------------------------
12
*/
13
#include "
postgres.h
"
14
15
#include "
catalog/pg_type.h
"
16
#include "
storage/predicate_internals.h
"
17
#include "
storage/proc.h
"
18
#include "
storage/procarray.h
"
19
#include "
utils/array.h
"
20
#include "utils/fmgrprotos.h"
21
#include "
utils/wait_event.h
"
22
23
#define UINT32_ACCESS_ONCE(var) ((uint32)(*((volatile uint32 *)&(var))))
24
25
26
/*
27
* pg_isolation_test_session_is_blocked - support function for isolationtester
28
*
29
* Check if specified PID is blocked by any of the PIDs listed in the second
30
* argument. Currently, this looks for blocking caused by waiting for
31
* injection points, heavyweight locks, or safe snapshots. We ignore blockage
32
* caused by PIDs not directly under the isolationtester's control, eg
33
* autovacuum.
34
*
35
* This is an undocumented function intended for use by the isolation tester,
36
* and may change in future releases as required for testing purposes.
37
*/
38
Datum
39
pg_isolation_test_session_is_blocked
(
PG_FUNCTION_ARGS
)
40
{
41
int
blocked_pid =
PG_GETARG_INT32
(0);
42
ArrayType
*interesting_pids_a =
PG_GETARG_ARRAYTYPE_P
(1);
43
PGPROC
*proc;
44
const
char
*wait_event_type;
45
ArrayType
*blocking_pids_a;
46
int32
*interesting_pids;
47
int32
*blocking_pids;
48
int
num_interesting_pids;
49
int
num_blocking_pids;
50
int
dummy;
51
int
i
,
52
j
;
53
54
/* Check if blocked_pid is in an injection point. */
55
proc =
BackendPidGetProc
(blocked_pid);
56
if
(proc == NULL)
57
PG_RETURN_BOOL
(
false
);
/* session gone: definitely unblocked */
58
wait_event_type =
59
pgstat_get_wait_event_type
(
UINT32_ACCESS_ONCE
(proc->
wait_event_info
));
60
if
(wait_event_type && strcmp(
"InjectionPoint"
, wait_event_type) == 0)
61
PG_RETURN_BOOL
(
true
);
62
63
/* Validate the passed-in array */
64
Assert
(
ARR_ELEMTYPE
(interesting_pids_a) == INT4OID);
65
if
(
array_contains_nulls
(interesting_pids_a))
66
elog
(
ERROR
,
"array must not contain nulls"
);
67
interesting_pids = (
int32
*)
ARR_DATA_PTR
(interesting_pids_a);
68
num_interesting_pids =
ArrayGetNItems
(
ARR_NDIM
(interesting_pids_a),
69
ARR_DIMS
(interesting_pids_a));
70
71
/*
72
* Get the PIDs of all sessions blocking the given session's attempt to
73
* acquire heavyweight locks.
74
*/
75
blocking_pids_a =
76
DatumGetArrayTypeP
(
DirectFunctionCall1
(
pg_blocking_pids
,
Int32GetDatum
(blocked_pid)));
77
78
Assert
(
ARR_ELEMTYPE
(blocking_pids_a) == INT4OID);
79
Assert
(!
array_contains_nulls
(blocking_pids_a));
80
blocking_pids = (
int32
*)
ARR_DATA_PTR
(blocking_pids_a);
81
num_blocking_pids =
ArrayGetNItems
(
ARR_NDIM
(blocking_pids_a),
82
ARR_DIMS
(blocking_pids_a));
83
84
/*
85
* Check if any of these are in the list of interesting PIDs, that being
86
* the sessions that the isolation tester is running. We don't use
87
* "arrayoverlaps" here, because it would lead to cache lookups and one of
88
* our goals is to run quickly with debug_discard_caches > 0. We expect
89
* blocking_pids to be usually empty and otherwise a very small number in
90
* isolation tester cases, so make that the outer loop of a naive search
91
* for a match.
92
*/
93
for
(
i
= 0;
i
< num_blocking_pids;
i
++)
94
for
(
j
= 0;
j
< num_interesting_pids;
j
++)
95
{
96
if
(blocking_pids[
i
] == interesting_pids[
j
])
97
PG_RETURN_BOOL
(
true
);
98
}
99
100
/*
101
* Check if blocked_pid is waiting for a safe snapshot. We could in
102
* theory check the resulting array of blocker PIDs against the
103
* interesting PIDs list, but since there is no danger of autovacuum
104
* blocking GetSafeSnapshot there seems to be no point in expending cycles
105
* on allocating a buffer and searching for overlap; so it's presently
106
* sufficient for the isolation tester's purposes to use a single element
107
* buffer and check if the number of safe snapshot blockers is non-zero.
108
*/
109
if
(
GetSafeSnapshotBlockingPids
(blocked_pid, &dummy, 1) > 0)
110
PG_RETURN_BOOL
(
true
);
111
112
PG_RETURN_BOOL
(
false
);
113
}
array.h
ARR_NDIM
#define ARR_NDIM(a)
Definition:
array.h:290
PG_GETARG_ARRAYTYPE_P
#define PG_GETARG_ARRAYTYPE_P(n)
Definition:
array.h:263
ARR_DATA_PTR
#define ARR_DATA_PTR(a)
Definition:
array.h:322
DatumGetArrayTypeP
#define DatumGetArrayTypeP(X)
Definition:
array.h:261
ARR_ELEMTYPE
#define ARR_ELEMTYPE(a)
Definition:
array.h:292
ARR_DIMS
#define ARR_DIMS(a)
Definition:
array.h:294
array_contains_nulls
bool array_contains_nulls(const ArrayType *array)
Definition:
arrayfuncs.c:3768
ArrayGetNItems
int ArrayGetNItems(int ndim, const int *dims)
Definition:
arrayutils.c:57
int32
int32_t int32
Definition:
c.h:539
ERROR
#define ERROR
Definition:
elog.h:39
elog
#define elog(elevel,...)
Definition:
elog.h:226
DirectFunctionCall1
#define DirectFunctionCall1(func, arg1)
Definition:
fmgr.h:682
PG_GETARG_INT32
#define PG_GETARG_INT32(n)
Definition:
fmgr.h:269
PG_FUNCTION_ARGS
#define PG_FUNCTION_ARGS
Definition:
fmgr.h:193
PG_RETURN_BOOL
#define PG_RETURN_BOOL(x)
Definition:
fmgr.h:359
Assert
Assert(PointerIsAligned(start, uint64))
j
int j
Definition:
isn.c:78
i
int i
Definition:
isn.c:77
pg_blocking_pids
Datum pg_blocking_pids(PG_FUNCTION_ARGS)
Definition:
lockfuncs.c:466
pg_type.h
postgres.h
Datum
uint64_t Datum
Definition:
postgres.h:70
Int32GetDatum
static Datum Int32GetDatum(int32 X)
Definition:
postgres.h:222
GetSafeSnapshotBlockingPids
int GetSafeSnapshotBlockingPids(int blocked_pid, int *output, int output_size)
Definition:
predicate.c:1628
predicate_internals.h
proc.h
BackendPidGetProc
PGPROC * BackendPidGetProc(int pid)
Definition:
procarray.c:3158
procarray.h
ArrayType
Definition:
array.h:93
PGPROC
Definition:
proc.h:179
PGPROC::wait_event_info
uint32 wait_event_info
Definition:
proc.h:296
pgstat_get_wait_event_type
const char * pgstat_get_wait_event_type(uint32 wait_event_info)
Definition:
wait_event.c:373
wait_event.h
UINT32_ACCESS_ONCE
#define UINT32_ACCESS_ONCE(var)
Definition:
waitfuncs.c:23
pg_isolation_test_session_is_blocked
Datum pg_isolation_test_session_is_blocked(PG_FUNCTION_ARGS)
Definition:
waitfuncs.c:39
src
backend
utils
adt
waitfuncs.c
Generated on Fri Nov 21 2025 06:13:14 for PostgreSQL Source Code by
1.9.4