Skip to content

Commit 2047ad0

Browse files
Cross-check lists of built-in LWLock tranches.
lwlock.c, lwlock.h, and wait_event_names.txt each contain a list of built-in LWLock tranches. It is easy to miss one or the other when adding or removing tranches, and discrepancies have adverse effects (e.g., breaking JOINs between pg_stat_activity and pg_wait_events). This commit moves the lists of built-in tranches in lwlock.{c,h} to lwlocklist.h and adds a cross-check to the script that generates lwlocknames.h. If the lists do not match exactly, building will fail. Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Reviewed-by: Michael Paquier <michael@paquier.xyz> Discussion: https://postgr.es/m/aHpOgwuFQfcFMZ/B%40ip-10-97-1-34.eu-west-3.compute.internal
1 parent 37c7a7e commit 2047ad0

File tree

5 files changed

+162
-119
lines changed

5 files changed

+162
-119
lines changed

src/backend/storage/lmgr/generate-lwlocknames.pl

Lines changed: 83 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,24 @@
2727

2828

2929
#
30-
# First, record the predefined LWLocks listed in wait_event_names.txt. We'll
31-
# cross-check those with the ones in lwlocklist.h.
30+
# First, record the predefined LWLocks and built-in tranches listed in
31+
# wait_event_names.txt. We'll cross-check those with the ones in lwlocklist.h.
3232
#
33+
my @wait_event_tranches;
3334
my @wait_event_lwlocks;
3435
my $record_lwlocks = 0;
36+
my $in_tranches = 0;
3537

3638
while (<$wait_event_names>)
3739
{
3840
chomp;
3941

4042
# Check for end marker.
41-
last if /^# END OF PREDEFINED LWLOCKS/;
43+
if (/^# END OF PREDEFINED LWLOCKS/)
44+
{
45+
$in_tranches = 1;
46+
next;
47+
}
4248

4349
# Skip comments and empty lines.
4450
next if /^#/;
@@ -54,13 +60,29 @@
5460
# Go to the next line if we are not yet recording LWLocks.
5561
next if not $record_lwlocks;
5662

63+
# Stop recording if we reach another section.
64+
last if /^Section:/;
65+
5766
# Record the LWLock.
5867
(my $waiteventname, my $waitevendocsentence) = split(/\t/, $_);
59-
push(@wait_event_lwlocks, $waiteventname);
68+
69+
if ($in_tranches)
70+
{
71+
push(@wait_event_tranches, $waiteventname);
72+
}
73+
else
74+
{
75+
push(@wait_event_lwlocks, $waiteventname);
76+
}
6077
}
6178

79+
#
80+
# While gathering the list of predefined LWLocks, cross-check the lists in
81+
# lwlocklist.h with the wait events we just recorded.
82+
#
6283
my $in_comment = 0;
63-
my $i = 0;
84+
my $lwlock_count = 0;
85+
my $tranche_count = 0;
6486
while (<$lwlocklist>)
6587
{
6688
chomp;
@@ -81,38 +103,72 @@
81103
next;
82104
}
83105

84-
die "unable to parse lwlocklist.h line \"$_\""
85-
unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/;
106+
#
107+
# Gather list of predefined LWLocks and cross-check with the wait events.
108+
#
109+
if (/^PG_LWLOCK\((\d+),\s+(\w+)\)$/)
110+
{
111+
my ($lockidx, $lockname) = ($1, $2);
86112

87-
(my $lockidx, my $lockname) = ($1, $2);
113+
die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
114+
die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
88115

89-
die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
90-
die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
116+
die "$lockname defined in lwlocklist.h but missing from "
117+
. "wait_event_names.txt"
118+
if $lwlock_count >= scalar @wait_event_lwlocks;
119+
die "lists of predefined LWLocks do not match (first mismatch at "
120+
. "$wait_event_lwlocks[$lwlock_count] in wait_event_names.txt and "
121+
. "$lockname in lwlocklist.h)"
122+
if $wait_event_lwlocks[$lwlock_count] ne $lockname;
91123

92-
die "$lockname defined in lwlocklist.h but missing from "
93-
. "wait_event_names.txt"
94-
if $i >= scalar @wait_event_lwlocks;
95-
die "lists of predefined LWLocks do not match (first mismatch at "
96-
. "$wait_event_lwlocks[$i] in wait_event_names.txt and $lockname in "
97-
. "lwlocklist.h)"
98-
if $wait_event_lwlocks[$i] ne $lockname;
99-
$i++;
124+
$lwlock_count++;
100125

101-
while ($lastlockidx < $lockidx - 1)
126+
while ($lastlockidx < $lockidx - 1)
127+
{
128+
++$lastlockidx;
129+
}
130+
$lastlockidx = $lockidx;
131+
132+
# Add a "Lock" suffix to each lock name, as the C code depends on that.
133+
printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
134+
$lockname . "Lock";
135+
136+
next;
137+
}
138+
139+
#
140+
# Cross-check the built-in LWLock tranches with the wait events.
141+
#
142+
if (/^PG_LWLOCKTRANCHE\((\w+),\s+(\w+)\)$/)
102143
{
103-
++$lastlockidx;
144+
my ($tranche_id, $tranche_name) = ($1, $2);
145+
146+
die "$tranche_name defined in lwlocklist.h but missing from "
147+
. "wait_event_names.txt"
148+
if $tranche_count >= scalar @wait_event_tranches;
149+
die
150+
"lists of built-in LWLock tranches do not match (first mismatch at "
151+
. "$wait_event_tranches[$tranche_count] in wait_event_names.txt and "
152+
. "$tranche_name in lwlocklist.h)"
153+
if $wait_event_tranches[$tranche_count] ne $tranche_name;
154+
155+
$tranche_count++;
156+
157+
next;
104158
}
105-
$lastlockidx = $lockidx;
106159

107-
# Add a "Lock" suffix to each lock name, as the C code depends on that
108-
printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
109-
$lockname . "Lock";
160+
die "unable to parse lwlocklist.h line \"$_\"";
110161
}
111162

112163
die
113-
"$wait_event_lwlocks[$i] defined in wait_event_names.txt but missing from "
114-
. "lwlocklist.h"
115-
if $i < scalar @wait_event_lwlocks;
164+
"$wait_event_lwlocks[$lwlock_count] defined in wait_event_names.txt but "
165+
. " missing from lwlocklist.h"
166+
if $lwlock_count < scalar @wait_event_lwlocks;
167+
168+
die
169+
"$wait_event_tranches[$tranche_count] defined in wait_event_names.txt but "
170+
. "missing from lwlocklist.h"
171+
if $tranche_count < scalar @wait_event_tranches;
116172

117173
print $h "\n";
118174
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;

src/backend/storage/lmgr/lwlock.c

Lines changed: 4 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,8 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
122122
* own tranche. We absorb the names of these tranches from there into
123123
* BuiltinTrancheNames here.
124124
*
125-
* 2. There are some predefined tranches for built-in groups of locks.
126-
* These are listed in enum BuiltinTrancheIds in lwlock.h, and their names
127-
* appear in BuiltinTrancheNames[] below.
125+
* 2. There are some predefined tranches for built-in groups of locks defined
126+
* in lwlocklist.h. We absorb the names of these tranches, too.
128127
*
129128
* 3. Extensions can create new tranches, via either RequestNamedLWLockTranche
130129
* or LWLockRegisterTranche. The names of these that are known in the current
@@ -135,49 +134,10 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
135134
*/
136135
static const char *const BuiltinTrancheNames[] = {
137136
#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname),
137+
#define PG_LWLOCKTRANCHE(id, lockname) [LWTRANCHE_##id] = CppAsString(lockname),
138138
#include "storage/lwlocklist.h"
139139
#undef PG_LWLOCK
140-
[LWTRANCHE_XACT_BUFFER] = "XactBuffer",
141-
[LWTRANCHE_COMMITTS_BUFFER] = "CommitTsBuffer",
142-
[LWTRANCHE_SUBTRANS_BUFFER] = "SubtransBuffer",
143-
[LWTRANCHE_MULTIXACTOFFSET_BUFFER] = "MultiXactOffsetBuffer",
144-
[LWTRANCHE_MULTIXACTMEMBER_BUFFER] = "MultiXactMemberBuffer",
145-
[LWTRANCHE_NOTIFY_BUFFER] = "NotifyBuffer",
146-
[LWTRANCHE_SERIAL_BUFFER] = "SerialBuffer",
147-
[LWTRANCHE_WAL_INSERT] = "WALInsert",
148-
[LWTRANCHE_BUFFER_CONTENT] = "BufferContent",
149-
[LWTRANCHE_REPLICATION_ORIGIN_STATE] = "ReplicationOriginState",
150-
[LWTRANCHE_REPLICATION_SLOT_IO] = "ReplicationSlotIO",
151-
[LWTRANCHE_LOCK_FASTPATH] = "LockFastPath",
152-
[LWTRANCHE_BUFFER_MAPPING] = "BufferMapping",
153-
[LWTRANCHE_LOCK_MANAGER] = "LockManager",
154-
[LWTRANCHE_PREDICATE_LOCK_MANAGER] = "PredicateLockManager",
155-
[LWTRANCHE_PARALLEL_HASH_JOIN] = "ParallelHashJoin",
156-
[LWTRANCHE_PARALLEL_BTREE_SCAN] = "ParallelBtreeScan",
157-
[LWTRANCHE_PARALLEL_QUERY_DSA] = "ParallelQueryDSA",
158-
[LWTRANCHE_PER_SESSION_DSA] = "PerSessionDSA",
159-
[LWTRANCHE_PER_SESSION_RECORD_TYPE] = "PerSessionRecordType",
160-
[LWTRANCHE_PER_SESSION_RECORD_TYPMOD] = "PerSessionRecordTypmod",
161-
[LWTRANCHE_SHARED_TUPLESTORE] = "SharedTupleStore",
162-
[LWTRANCHE_SHARED_TIDBITMAP] = "SharedTidBitmap",
163-
[LWTRANCHE_PARALLEL_APPEND] = "ParallelAppend",
164-
[LWTRANCHE_PER_XACT_PREDICATE_LIST] = "PerXactPredicateList",
165-
[LWTRANCHE_PGSTATS_DSA] = "PgStatsDSA",
166-
[LWTRANCHE_PGSTATS_HASH] = "PgStatsHash",
167-
[LWTRANCHE_PGSTATS_DATA] = "PgStatsData",
168-
[LWTRANCHE_LAUNCHER_DSA] = "LogicalRepLauncherDSA",
169-
[LWTRANCHE_LAUNCHER_HASH] = "LogicalRepLauncherHash",
170-
[LWTRANCHE_DSM_REGISTRY_DSA] = "DSMRegistryDSA",
171-
[LWTRANCHE_DSM_REGISTRY_HASH] = "DSMRegistryHash",
172-
[LWTRANCHE_COMMITTS_SLRU] = "CommitTsSLRU",
173-
[LWTRANCHE_MULTIXACTOFFSET_SLRU] = "MultiXactOffsetSLRU",
174-
[LWTRANCHE_MULTIXACTMEMBER_SLRU] = "MultiXactMemberSLRU",
175-
[LWTRANCHE_NOTIFY_SLRU] = "NotifySLRU",
176-
[LWTRANCHE_SERIAL_SLRU] = "SerialSLRU",
177-
[LWTRANCHE_SUBTRANS_SLRU] = "SubtransSLRU",
178-
[LWTRANCHE_XACT_SLRU] = "XactSLRU",
179-
[LWTRANCHE_PARALLEL_VACUUM_DSA] = "ParallelVacuumDSA",
180-
[LWTRANCHE_AIO_URING_COMPLETION] = "AioUringCompletion",
140+
#undef PG_LWLOCKTRANCHE
181141
};
182142

183143
StaticAssertDecl(lengthof(BuiltinTrancheNames) ==

src/backend/utils/activity/wait_event_names.txt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,13 @@ AioWorkerSubmissionQueue "Waiting to access AIO worker submission queue."
356356
#
357357
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
358358
#
359-
# Predefined LWLocks (i.e., those declared in lwlocknames.h) must be listed
360-
# in the section above and must be listed in the same order as in
361-
# lwlocknames.h. Other LWLocks must be listed in the section below.
359+
# Predefined LWLocks (i.e., those declared at the top of lwlocknames.h) must be
360+
# listed in the section above and must be listed in the same order as in
361+
# lwlocknames.h.
362+
#
363+
# Likewise, the built-in LWLock tranches (i.e., those declared at the bottom of
364+
# lwlocknames.h) must be listed in the section below and must be listed in the
365+
# same order as in lwlocknames.h.
362366
#
363367

364368
XactBuffer "Waiting for I/O on a transaction status SLRU buffer."

src/include/storage/lwlock.h

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -176,51 +176,23 @@ extern void LWLockInitialize(LWLock *lock, int tranche_id);
176176
* Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
177177
* we reserve additional tranche IDs for builtin tranches not included in
178178
* the set of individual LWLocks. A call to LWLockNewTrancheId will never
179-
* return a value less than LWTRANCHE_FIRST_USER_DEFINED.
179+
* return a value less than LWTRANCHE_FIRST_USER_DEFINED. The actual list of
180+
* built-in tranches is kept in lwlocklist.h.
180181
*/
181182
typedef enum BuiltinTrancheIds
182183
{
183-
LWTRANCHE_XACT_BUFFER = NUM_INDIVIDUAL_LWLOCKS,
184-
LWTRANCHE_COMMITTS_BUFFER,
185-
LWTRANCHE_SUBTRANS_BUFFER,
186-
LWTRANCHE_MULTIXACTOFFSET_BUFFER,
187-
LWTRANCHE_MULTIXACTMEMBER_BUFFER,
188-
LWTRANCHE_NOTIFY_BUFFER,
189-
LWTRANCHE_SERIAL_BUFFER,
190-
LWTRANCHE_WAL_INSERT,
191-
LWTRANCHE_BUFFER_CONTENT,
192-
LWTRANCHE_REPLICATION_ORIGIN_STATE,
193-
LWTRANCHE_REPLICATION_SLOT_IO,
194-
LWTRANCHE_LOCK_FASTPATH,
195-
LWTRANCHE_BUFFER_MAPPING,
196-
LWTRANCHE_LOCK_MANAGER,
197-
LWTRANCHE_PREDICATE_LOCK_MANAGER,
198-
LWTRANCHE_PARALLEL_HASH_JOIN,
199-
LWTRANCHE_PARALLEL_BTREE_SCAN,
200-
LWTRANCHE_PARALLEL_QUERY_DSA,
201-
LWTRANCHE_PER_SESSION_DSA,
202-
LWTRANCHE_PER_SESSION_RECORD_TYPE,
203-
LWTRANCHE_PER_SESSION_RECORD_TYPMOD,
204-
LWTRANCHE_SHARED_TUPLESTORE,
205-
LWTRANCHE_SHARED_TIDBITMAP,
206-
LWTRANCHE_PARALLEL_APPEND,
207-
LWTRANCHE_PER_XACT_PREDICATE_LIST,
208-
LWTRANCHE_PGSTATS_DSA,
209-
LWTRANCHE_PGSTATS_HASH,
210-
LWTRANCHE_PGSTATS_DATA,
211-
LWTRANCHE_LAUNCHER_DSA,
212-
LWTRANCHE_LAUNCHER_HASH,
213-
LWTRANCHE_DSM_REGISTRY_DSA,
214-
LWTRANCHE_DSM_REGISTRY_HASH,
215-
LWTRANCHE_COMMITTS_SLRU,
216-
LWTRANCHE_MULTIXACTMEMBER_SLRU,
217-
LWTRANCHE_MULTIXACTOFFSET_SLRU,
218-
LWTRANCHE_NOTIFY_SLRU,
219-
LWTRANCHE_SERIAL_SLRU,
220-
LWTRANCHE_SUBTRANS_SLRU,
221-
LWTRANCHE_XACT_SLRU,
222-
LWTRANCHE_PARALLEL_VACUUM_DSA,
223-
LWTRANCHE_AIO_URING_COMPLETION,
184+
/*
185+
* LWTRANCHE_INVALID is an unused value that only exists to initialize the
186+
* rest of the tranches to appropriate values.
187+
*/
188+
LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
189+
190+
#define PG_LWLOCK(id, name)
191+
#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
192+
#include "storage/lwlocklist.h"
193+
#undef PG_LWLOCK
194+
#undef PG_LWLOCKTRANCHE
195+
224196
LWTRANCHE_FIRST_USER_DEFINED,
225197
} BuiltinTrancheIds;
226198

src/include/storage/lwlocklist.h

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
*
33
* lwlocklist.h
44
*
5-
* The predefined LWLock list is kept in its own source file for use by
6-
* automatic tools. The exact representation of a keyword is determined by
7-
* the PG_LWLOCK macro, which is not defined in this file; it can be
5+
* The list of predefined LWLocks and built-in LWLock tranches is kept in
6+
* its own source file for use by automatic tools. The exact
7+
* representation of a keyword is determined by the PG_LWLOCK and
8+
* PG_LWLOCKTRANCHE macros, which are not defined in this file; they can be
89
* defined by the caller for special purposes.
910
*
1011
* Also, generate-lwlocknames.pl processes this file to create lwlocknames.h.
@@ -84,3 +85,53 @@ PG_LWLOCK(50, DSMRegistry)
8485
PG_LWLOCK(51, InjectionPoint)
8586
PG_LWLOCK(52, SerialControl)
8687
PG_LWLOCK(53, AioWorkerSubmissionQueue)
88+
89+
/*
90+
* There also exist several built-in LWLock tranches. As with the predefined
91+
* LWLocks, be sure to update the WaitEventLWLock section of
92+
* src/backend/utils/activity/wait_event_names.txt when modifying this list.
93+
*
94+
* Note that the IDs here (the first value) don't include the LWTRANCHE_
95+
* prefix. It's added elsewhere.
96+
*/
97+
PG_LWLOCKTRANCHE(XACT_BUFFER, XactBuffer)
98+
PG_LWLOCKTRANCHE(COMMITTS_BUFFER, CommitTsBuffer)
99+
PG_LWLOCKTRANCHE(SUBTRANS_BUFFER, SubtransBuffer)
100+
PG_LWLOCKTRANCHE(MULTIXACTOFFSET_BUFFER, MultiXactOffsetBuffer)
101+
PG_LWLOCKTRANCHE(MULTIXACTMEMBER_BUFFER, MultiXactMemberBuffer)
102+
PG_LWLOCKTRANCHE(NOTIFY_BUFFER, NotifyBuffer)
103+
PG_LWLOCKTRANCHE(SERIAL_BUFFER, SerialBuffer)
104+
PG_LWLOCKTRANCHE(WAL_INSERT, WALInsert)
105+
PG_LWLOCKTRANCHE(BUFFER_CONTENT, BufferContent)
106+
PG_LWLOCKTRANCHE(REPLICATION_ORIGIN_STATE, ReplicationOriginState)
107+
PG_LWLOCKTRANCHE(REPLICATION_SLOT_IO, ReplicationSlotIO)
108+
PG_LWLOCKTRANCHE(LOCK_FASTPATH, LockFastPath)
109+
PG_LWLOCKTRANCHE(BUFFER_MAPPING, BufferMapping)
110+
PG_LWLOCKTRANCHE(LOCK_MANAGER, LockManager)
111+
PG_LWLOCKTRANCHE(PREDICATE_LOCK_MANAGER, PredicateLockManager)
112+
PG_LWLOCKTRANCHE(PARALLEL_HASH_JOIN, ParallelHashJoin)
113+
PG_LWLOCKTRANCHE(PARALLEL_BTREE_SCAN, ParallelBtreeScan)
114+
PG_LWLOCKTRANCHE(PARALLEL_QUERY_DSA, ParallelQueryDSA)
115+
PG_LWLOCKTRANCHE(PER_SESSION_DSA, PerSessionDSA)
116+
PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPE, PerSessionRecordType)
117+
PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPMOD, PerSessionRecordTypmod)
118+
PG_LWLOCKTRANCHE(SHARED_TUPLESTORE, SharedTupleStore)
119+
PG_LWLOCKTRANCHE(SHARED_TIDBITMAP, SharedTidBitmap)
120+
PG_LWLOCKTRANCHE(PARALLEL_APPEND, ParallelAppend)
121+
PG_LWLOCKTRANCHE(PER_XACT_PREDICATE_LIST, PerXactPredicateList)
122+
PG_LWLOCKTRANCHE(PGSTATS_DSA, PgStatsDSA)
123+
PG_LWLOCKTRANCHE(PGSTATS_HASH, PgStatsHash)
124+
PG_LWLOCKTRANCHE(PGSTATS_DATA, PgStatsData)
125+
PG_LWLOCKTRANCHE(LAUNCHER_DSA, LogicalRepLauncherDSA)
126+
PG_LWLOCKTRANCHE(LAUNCHER_HASH, LogicalRepLauncherHash)
127+
PG_LWLOCKTRANCHE(DSM_REGISTRY_DSA, DSMRegistryDSA)
128+
PG_LWLOCKTRANCHE(DSM_REGISTRY_HASH, DSMRegistryHash)
129+
PG_LWLOCKTRANCHE(COMMITTS_SLRU, CommitTsSLRU)
130+
PG_LWLOCKTRANCHE(MULTIXACTOFFSET_SLRU, MultiXactOffsetSLRU)
131+
PG_LWLOCKTRANCHE(MULTIXACTMEMBER_SLRU, MultiXactMemberSLRU)
132+
PG_LWLOCKTRANCHE(NOTIFY_SLRU, NotifySLRU)
133+
PG_LWLOCKTRANCHE(SERIAL_SLRU, SerialSLRU)
134+
PG_LWLOCKTRANCHE(SUBTRANS_SLRU, SubtransSLRU)
135+
PG_LWLOCKTRANCHE(XACT_SLRU, XactSLRU)
136+
PG_LWLOCKTRANCHE(PARALLEL_VACUUM_DSA, ParallelVacuumDSA)
137+
PG_LWLOCKTRANCHE(AIO_URING_COMPLETION, AioUringCompletion)

0 commit comments

Comments
 (0)