1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-18 02:02:55 +03:00

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
This commit is contained in:
Nathan Bossart
2025-07-23 12:06:20 -05:00
parent 37c7a7eeb6
commit 2047ad0681
5 changed files with 167 additions and 124 deletions

View File

@@ -27,18 +27,24 @@ print $h "/* there is deliberately not an #ifndef LWLOCKNAMES_H here */\n\n";
#
# First, record the predefined LWLocks listed in wait_event_names.txt. We'll
# cross-check those with the ones in lwlocklist.h.
# First, record the predefined LWLocks and built-in tranches listed in
# wait_event_names.txt. We'll cross-check those with the ones in lwlocklist.h.
#
my @wait_event_tranches;
my @wait_event_lwlocks;
my $record_lwlocks = 0;
my $in_tranches = 0;
while (<$wait_event_names>)
{
chomp;
# Check for end marker.
last if /^# END OF PREDEFINED LWLOCKS/;
if (/^# END OF PREDEFINED LWLOCKS/)
{
$in_tranches = 1;
next;
}
# Skip comments and empty lines.
next if /^#/;
@@ -54,13 +60,29 @@ while (<$wait_event_names>)
# Go to the next line if we are not yet recording LWLocks.
next if not $record_lwlocks;
# Stop recording if we reach another section.
last if /^Section:/;
# Record the LWLock.
(my $waiteventname, my $waitevendocsentence) = split(/\t/, $_);
push(@wait_event_lwlocks, $waiteventname);
if ($in_tranches)
{
push(@wait_event_tranches, $waiteventname);
}
else
{
push(@wait_event_lwlocks, $waiteventname);
}
}
#
# While gathering the list of predefined LWLocks, cross-check the lists in
# lwlocklist.h with the wait events we just recorded.
#
my $in_comment = 0;
my $i = 0;
my $lwlock_count = 0;
my $tranche_count = 0;
while (<$lwlocklist>)
{
chomp;
@@ -81,38 +103,72 @@ while (<$lwlocklist>)
next;
}
die "unable to parse lwlocklist.h line \"$_\""
unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/;
(my $lockidx, my $lockname) = ($1, $2);
die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
die "$lockname defined in lwlocklist.h but missing from "
. "wait_event_names.txt"
if $i >= scalar @wait_event_lwlocks;
die "lists of predefined LWLocks do not match (first mismatch at "
. "$wait_event_lwlocks[$i] in wait_event_names.txt and $lockname in "
. "lwlocklist.h)"
if $wait_event_lwlocks[$i] ne $lockname;
$i++;
while ($lastlockidx < $lockidx - 1)
#
# Gather list of predefined LWLocks and cross-check with the wait events.
#
if (/^PG_LWLOCK\((\d+),\s+(\w+)\)$/)
{
++$lastlockidx;
}
$lastlockidx = $lockidx;
my ($lockidx, $lockname) = ($1, $2);
# Add a "Lock" suffix to each lock name, as the C code depends on that
printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
$lockname . "Lock";
die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
die "$lockname defined in lwlocklist.h but missing from "
. "wait_event_names.txt"
if $lwlock_count >= scalar @wait_event_lwlocks;
die "lists of predefined LWLocks do not match (first mismatch at "
. "$wait_event_lwlocks[$lwlock_count] in wait_event_names.txt and "
. "$lockname in lwlocklist.h)"
if $wait_event_lwlocks[$lwlock_count] ne $lockname;
$lwlock_count++;
while ($lastlockidx < $lockidx - 1)
{
++$lastlockidx;
}
$lastlockidx = $lockidx;
# Add a "Lock" suffix to each lock name, as the C code depends on that.
printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
$lockname . "Lock";
next;
}
#
# Cross-check the built-in LWLock tranches with the wait events.
#
if (/^PG_LWLOCKTRANCHE\((\w+),\s+(\w+)\)$/)
{
my ($tranche_id, $tranche_name) = ($1, $2);
die "$tranche_name defined in lwlocklist.h but missing from "
. "wait_event_names.txt"
if $tranche_count >= scalar @wait_event_tranches;
die
"lists of built-in LWLock tranches do not match (first mismatch at "
. "$wait_event_tranches[$tranche_count] in wait_event_names.txt and "
. "$tranche_name in lwlocklist.h)"
if $wait_event_tranches[$tranche_count] ne $tranche_name;
$tranche_count++;
next;
}
die "unable to parse lwlocklist.h line \"$_\"";
}
die
"$wait_event_lwlocks[$i] defined in wait_event_names.txt but missing from "
. "lwlocklist.h"
if $i < scalar @wait_event_lwlocks;
"$wait_event_lwlocks[$lwlock_count] defined in wait_event_names.txt but "
. " missing from lwlocklist.h"
if $lwlock_count < scalar @wait_event_lwlocks;
die
"$wait_event_tranches[$tranche_count] defined in wait_event_names.txt but "
. "missing from lwlocklist.h"
if $tranche_count < scalar @wait_event_tranches;
print $h "\n";
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;

View File

@@ -122,9 +122,8 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
* own tranche. We absorb the names of these tranches from there into
* BuiltinTrancheNames here.
*
* 2. There are some predefined tranches for built-in groups of locks.
* These are listed in enum BuiltinTrancheIds in lwlock.h, and their names
* appear in BuiltinTrancheNames[] below.
* 2. There are some predefined tranches for built-in groups of locks defined
* in lwlocklist.h. We absorb the names of these tranches, too.
*
* 3. Extensions can create new tranches, via either RequestNamedLWLockTranche
* or LWLockRegisterTranche. The names of these that are known in the current
@@ -135,49 +134,10 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
*/
static const char *const BuiltinTrancheNames[] = {
#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname),
#define PG_LWLOCKTRANCHE(id, lockname) [LWTRANCHE_##id] = CppAsString(lockname),
#include "storage/lwlocklist.h"
#undef PG_LWLOCK
[LWTRANCHE_XACT_BUFFER] = "XactBuffer",
[LWTRANCHE_COMMITTS_BUFFER] = "CommitTsBuffer",
[LWTRANCHE_SUBTRANS_BUFFER] = "SubtransBuffer",
[LWTRANCHE_MULTIXACTOFFSET_BUFFER] = "MultiXactOffsetBuffer",
[LWTRANCHE_MULTIXACTMEMBER_BUFFER] = "MultiXactMemberBuffer",
[LWTRANCHE_NOTIFY_BUFFER] = "NotifyBuffer",
[LWTRANCHE_SERIAL_BUFFER] = "SerialBuffer",
[LWTRANCHE_WAL_INSERT] = "WALInsert",
[LWTRANCHE_BUFFER_CONTENT] = "BufferContent",
[LWTRANCHE_REPLICATION_ORIGIN_STATE] = "ReplicationOriginState",
[LWTRANCHE_REPLICATION_SLOT_IO] = "ReplicationSlotIO",
[LWTRANCHE_LOCK_FASTPATH] = "LockFastPath",
[LWTRANCHE_BUFFER_MAPPING] = "BufferMapping",
[LWTRANCHE_LOCK_MANAGER] = "LockManager",
[LWTRANCHE_PREDICATE_LOCK_MANAGER] = "PredicateLockManager",
[LWTRANCHE_PARALLEL_HASH_JOIN] = "ParallelHashJoin",
[LWTRANCHE_PARALLEL_BTREE_SCAN] = "ParallelBtreeScan",
[LWTRANCHE_PARALLEL_QUERY_DSA] = "ParallelQueryDSA",
[LWTRANCHE_PER_SESSION_DSA] = "PerSessionDSA",
[LWTRANCHE_PER_SESSION_RECORD_TYPE] = "PerSessionRecordType",
[LWTRANCHE_PER_SESSION_RECORD_TYPMOD] = "PerSessionRecordTypmod",
[LWTRANCHE_SHARED_TUPLESTORE] = "SharedTupleStore",
[LWTRANCHE_SHARED_TIDBITMAP] = "SharedTidBitmap",
[LWTRANCHE_PARALLEL_APPEND] = "ParallelAppend",
[LWTRANCHE_PER_XACT_PREDICATE_LIST] = "PerXactPredicateList",
[LWTRANCHE_PGSTATS_DSA] = "PgStatsDSA",
[LWTRANCHE_PGSTATS_HASH] = "PgStatsHash",
[LWTRANCHE_PGSTATS_DATA] = "PgStatsData",
[LWTRANCHE_LAUNCHER_DSA] = "LogicalRepLauncherDSA",
[LWTRANCHE_LAUNCHER_HASH] = "LogicalRepLauncherHash",
[LWTRANCHE_DSM_REGISTRY_DSA] = "DSMRegistryDSA",
[LWTRANCHE_DSM_REGISTRY_HASH] = "DSMRegistryHash",
[LWTRANCHE_COMMITTS_SLRU] = "CommitTsSLRU",
[LWTRANCHE_MULTIXACTOFFSET_SLRU] = "MultiXactOffsetSLRU",
[LWTRANCHE_MULTIXACTMEMBER_SLRU] = "MultiXactMemberSLRU",
[LWTRANCHE_NOTIFY_SLRU] = "NotifySLRU",
[LWTRANCHE_SERIAL_SLRU] = "SerialSLRU",
[LWTRANCHE_SUBTRANS_SLRU] = "SubtransSLRU",
[LWTRANCHE_XACT_SLRU] = "XactSLRU",
[LWTRANCHE_PARALLEL_VACUUM_DSA] = "ParallelVacuumDSA",
[LWTRANCHE_AIO_URING_COMPLETION] = "AioUringCompletion",
#undef PG_LWLOCKTRANCHE
};
StaticAssertDecl(lengthof(BuiltinTrancheNames) ==

View File

@@ -356,9 +356,13 @@ AioWorkerSubmissionQueue "Waiting to access AIO worker submission queue."
#
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
#
# Predefined LWLocks (i.e., those declared in lwlocknames.h) must be listed
# in the section above and must be listed in the same order as in
# lwlocknames.h. Other LWLocks must be listed in the section below.
# Predefined LWLocks (i.e., those declared at the top of lwlocknames.h) must be
# listed in the section above and must be listed in the same order as in
# lwlocknames.h.
#
# Likewise, the built-in LWLock tranches (i.e., those declared at the bottom of
# lwlocknames.h) must be listed in the section below and must be listed in the
# same order as in lwlocknames.h.
#
XactBuffer "Waiting for I/O on a transaction status SLRU buffer."