Verify predefined LWLocks tranches have entries in wait_event_names.txt
Hi hackers,
Some discrepancies between wait_event_names.txt and predefined LWLocks tranches
have been observed, see: a493e741d32 ,08b9b9e043b and c3623703f36.
To prevent new discrepancies from occurring, this patch series aims to $SUBJECT
(as 5b1b9bce844 did for predefined LWLocks).
The patch series contains:
0001 - Extracts the predefined LWLocks tranches from lwlock.c and puts them
in a new file (namely lwlocktranchelist.h). This way, we can include this file
in lwlock.c using the same macro pattern as we do for lwlocklist.h.
This gives us the chance to cross-check with wait_event_names.txt in
generate-lwlocknames.pl in the same way as 5b1b9bce844 did.
It's much simpler and makes more sense than having generate-lwlocknames.pl
parsing lwlock.c.
0002 - While doing changes in generate-lwlocknames.pl, I noticed that
$continue is not used (Oversight in commit da952b415f4), so let's remove it.
0003 - Cross-check lists of predefined tranches
Same idea as 5b1b9bce844 i.e if the lists (in wait_event_names.txt and
lwlocktranchelist.h) do not match exactly, building will fail.
I wonder if once these get in, we could also generate "BuiltinTrancheIds" (in
lwlock.h) from lwlocktranchelist.h with generate-lwlocknames.pl.
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
Attachments:
v1-0002-Remove-unused-variable-in-generate-lwlocknames.pl.patchtext/x-diff; charset=us-asciiDownload
From 8cf82eb171eccf3144c5ca0050659c412b4b5069 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Fri, 18 Jul 2025 11:04:43 +0000
Subject: [PATCH v1 2/3] Remove unused variable in generate-lwlocknames.pl
$continue is not used, so let's remove it.
Oversight in commit da952b415f4.
---
src/backend/storage/lmgr/generate-lwlocknames.pl | 3 ---
1 file changed, 3 deletions(-)
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index 4441b7cba0c..c7a6720440d 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -10,7 +10,6 @@ use Getopt::Long;
my $output_path = '.';
my $lastlockidx = -1;
-my $continue = "\n";
GetOptions('outdir:s' => \$output_path);
@@ -102,10 +101,8 @@ while (<$lwlocklist>)
while ($lastlockidx < $lockidx - 1)
{
++$lastlockidx;
- $continue = ",\n";
}
$lastlockidx = $lockidx;
- $continue = ",\n";
# Add a "Lock" suffix to each lock name, as the C code depends on that
printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n",
--
2.34.1
v1-0001-Create-lwlocktranchelist.h.patchtext/x-diff; charset=us-asciiDownload
From 830e9dce82d42eddbd7281f4267bb771162dbd47 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Fri, 18 Jul 2025 10:03:18 +0000
Subject: [PATCH v1 1/3] Create lwlocktranchelist.h
This commit extracts the predefined LWLocks tranches from lwlock.c and puts them
in a new file (namely lwlocktranchelist.h).
This way, we can include this file in lwlock.c using the same macro pattern
as we do for lwlocklist.h.
This gives us the chance to cross-check with wait_event_names.txt in
generate-lwlocknames.pl in a following commit.
---
src/backend/storage/lmgr/lwlock.c | 47 ++--------------
src/include/storage/lwlocktranchelist.h | 72 +++++++++++++++++++++++++
src/tools/pginclude/headerscheck | 1 +
3 files changed, 78 insertions(+), 42 deletions(-)
create mode 100644 src/include/storage/lwlocktranchelist.h
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 2d43bf2cc13..9c6285ea4cb 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -124,7 +124,7 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
*
* 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.
+ * appear in lwlocktranchelist.h.
*
* 3. Extensions can create new tranches, via either RequestNamedLWLockTranche
* or LWLockRegisterTranche. The names of these that are known in the current
@@ -137,47 +137,10 @@ static const char *const BuiltinTrancheNames[] = {
#define PG_LWLOCK(id, lockname) [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",
+
+#define PG_BUILTIN_LWTRANCHE(id, name) [id] = name,
+#include "storage/lwlocktranchelist.h"
+#undef PG_BUILTIN_LWTRANCHE
};
StaticAssertDecl(lengthof(BuiltinTrancheNames) ==
diff --git a/src/include/storage/lwlocktranchelist.h b/src/include/storage/lwlocktranchelist.h
new file mode 100644
index 00000000000..5f45f5f8d0b
--- /dev/null
+++ b/src/include/storage/lwlocktranchelist.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * lwlocktranchelist.h
+ *
+ * The predefined built-in LWLock tranche list is kept in its own source
+ * file for use by automatic tools. The exact representation of a tranche
+ * is determined by the PG_BUILTIN_LWTRANCHE macro, which is not defined in
+ * this file; it can be defined by the caller for special purposes.
+ *
+ * Also, generate-lwlocknames.pl processes this file for validation against
+ * wait_event_names.txt.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/storage/lwlocktranchelist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * Predefined tranches for built-in groups of locks.
+ *
+ * If you add a tranche, do not forget to update the section WaitEventLWLock of
+ * wait_event_names.txt.
+ *
+ * Note that the tranche names here should match exactly what appears
+ * in wait_event_names.txt.
+ */
+
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_XACT_BUFFER, "XactBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_COMMITTS_BUFFER, "CommitTsBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_SUBTRANS_BUFFER, "SubtransBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_MULTIXACTOFFSET_BUFFER, "MultiXactOffsetBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_MULTIXACTMEMBER_BUFFER, "MultiXactMemberBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_NOTIFY_BUFFER, "NotifyBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_SERIAL_BUFFER, "SerialBuffer")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_WAL_INSERT, "WALInsert")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_BUFFER_CONTENT, "BufferContent")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_REPLICATION_ORIGIN_STATE, "ReplicationOriginState")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_REPLICATION_SLOT_IO, "ReplicationSlotIO")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_LOCK_FASTPATH, "LockFastPath")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_BUFFER_MAPPING, "BufferMapping")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_LOCK_MANAGER, "LockManager")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PREDICATE_LOCK_MANAGER, "PredicateLockManager")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PARALLEL_HASH_JOIN, "ParallelHashJoin")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PARALLEL_BTREE_SCAN, "ParallelBtreeScan")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PARALLEL_QUERY_DSA, "ParallelQueryDSA")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PER_SESSION_DSA, "PerSessionDSA")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PER_SESSION_RECORD_TYPE, "PerSessionRecordType")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PER_SESSION_RECORD_TYPMOD, "PerSessionRecordTypmod")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_SHARED_TUPLESTORE, "SharedTupleStore")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_SHARED_TIDBITMAP, "SharedTidBitmap")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PARALLEL_APPEND, "ParallelAppend")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PER_XACT_PREDICATE_LIST, "PerXactPredicateList")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PGSTATS_DSA, "PgStatsDSA")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PGSTATS_HASH, "PgStatsHash")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PGSTATS_DATA, "PgStatsData")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_LAUNCHER_DSA, "LogicalRepLauncherDSA")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_LAUNCHER_HASH, "LogicalRepLauncherHash")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_DSM_REGISTRY_DSA, "DSMRegistryDSA")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_DSM_REGISTRY_HASH, "DSMRegistryHash")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_COMMITTS_SLRU, "CommitTsSLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_MULTIXACTOFFSET_SLRU, "MultiXactOffsetSLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_MULTIXACTMEMBER_SLRU, "MultiXactMemberSLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_NOTIFY_SLRU, "NotifySLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_SERIAL_SLRU, "SerialSLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_SUBTRANS_SLRU, "SubtransSLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_XACT_SLRU, "XactSLRU")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_PARALLEL_VACUUM_DSA, "ParallelVacuumDSA")
+PG_BUILTIN_LWTRANCHE(LWTRANCHE_AIO_URING_COMPLETION, "AioUringCompletion")
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 9e86d049362..4dc5bfab995 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -132,6 +132,7 @@ do
test "$f" = src/interfaces/ecpg/preproc/ecpg_kwlist.h && continue
test "$f" = src/include/regex/regerrs.h && continue
test "$f" = src/include/storage/lwlocklist.h && continue
+ test "$f" = src/include/storage/lwlocktranchelist.h && continue
test "$f" = src/include/tcop/cmdtaglist.h && continue
test "$f" = src/pl/plpgsql/src/plerrcodes.h && continue
test "$f" = src/pl/plpython/spiexceptions.h && continue
--
2.34.1
v1-0003-Cross-check-lists-of-predefined-tranches.patchtext/x-diff; charset=us-asciiDownload
From a24e6af77e27589c9eaa5ceda017490c80bebad8 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Fri, 18 Jul 2025 11:19:19 +0000
Subject: [PATCH v1 3/3] Cross-check lists of predefined tranches.
Both builtin_lwlocktranchelist.h and wait_event_names.txt contain a list of all
the predefined tranches. It is easy to miss one or the other (see a493e741d32
,08b9b9e043b and c3623703f36).
This commit adds a cross-check of these lists to the script that already does
the same cross-check for lwlocklist.h.
If the lists do not match exactly, building will fail (same as in 5b1b9bce844).
---
src/backend/Makefile | 2 +-
src/backend/storage/lmgr/Makefile | 2 +-
.../storage/lmgr/generate-lwlocknames.pl | 77 +++++++++++++++++--
src/include/storage/meson.build | 1 +
4 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..cda1bbe2b35 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -111,7 +111,7 @@ $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
parser/gram.h: parser/gram.y
$(MAKE) -C parser gram.h
-storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl ../include/storage/lwlocklist.h utils/activity/wait_event_names.txt
+storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl ../include/storage/lwlocklist.h ../include/storage/lwlocktranchelist.h utils/activity/wait_event_names.txt
$(MAKE) -C storage/lmgr lwlocknames.h
utils/activity/wait_event_types.h: utils/activity/generate-wait_event_types.pl utils/activity/wait_event_names.txt
diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile
index 6cbaf23b855..523804889ae 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -33,7 +33,7 @@ s_lock_test: s_lock.c $(top_builddir)/src/common/libpgcommon.a $(top_builddir)/s
$(TASPATH) -L $(top_builddir)/src/common -lpgcommon \
-L $(top_builddir)/src/port -lpgport -lm -o s_lock_test
-lwlocknames.h: ../../../include/storage/lwlocklist.h ../../utils/activity/wait_event_names.txt generate-lwlocknames.pl
+lwlocknames.h: ../../../include/storage/lwlocklist.h ../../../include/storage/lwlocktranchelist.h ../../utils/activity/wait_event_names.txt generate-lwlocknames.pl
$(PERL) $(srcdir)/generate-lwlocknames.pl $^
check: s_lock_test
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index c7a6720440d..4732c17f03d 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -14,7 +14,8 @@ my $lastlockidx = -1;
GetOptions('outdir:s' => \$output_path);
open my $lwlocklist, '<', $ARGV[0] or die;
-open my $wait_event_names, '<', $ARGV[1] or die;
+open my $builtin_lwtranche_list, '<', $ARGV[1] or die;
+open my $wait_event_names, '<', $ARGV[2] or die;
# Include PID in suffix in case parallel make runs this multiple times.
my $htmp = "$output_path/lwlocknames.h.tmp$$";
@@ -27,18 +28,25 @@ 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
+# and in lwlocktranchelist.h.
#
+my @wait_event_builtin_tranches;
my @wait_event_lwlocks;
my $record_lwlocks = 0;
+my $in_builtin_tranches = 0;
while (<$wait_event_names>)
{
chomp;
- # Check for end marker.
- last if /^# END OF PREDEFINED LWLOCKS/;
+ # Check for predefined end marker.
+ if (/^# END OF PREDEFINED LWLOCKS/)
+ {
+ $in_builtin_tranches = 1;
+ next;
+ }
# Skip comments and empty lines.
next if /^#/;
@@ -54,9 +62,20 @@ 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_builtin_tranches)
+ {
+ push(@wait_event_builtin_tranches, $waiteventname);
+ }
+ else
+ {
+ push(@wait_event_lwlocks, $waiteventname);
+ }
}
my $in_comment = 0;
@@ -114,6 +133,52 @@ die
. "lwlocklist.h"
if $i < scalar @wait_event_lwlocks;
+$in_comment = 0;
+$i = 0;
+
+# Cross-check the built-in tranches in lwlocktranchelist.h with
+# wait_event_names.txt.
+while (<$builtin_lwtranche_list>)
+{
+ chomp;
+
+ # Skip single-line C comments and empty lines
+ next if m{^\s*/\*.*\*/$};
+ next if /^\s*$/;
+
+ # skip multiline C comments
+ if ($in_comment == 1)
+ {
+ $in_comment = 0 if m{\*/};
+ next;
+ }
+ elsif (m{^\s*/\*})
+ {
+ $in_comment = 1;
+ next;
+ }
+
+ die "unable to parse lwlocktranchelist.h line \"$_\""
+ unless /^PG_BUILTIN_LWTRANCHE\((\w+),\s*"([^"]+)"\)$/;
+
+ my ($tranche_id, $tranche_name) = ($1, $2);
+
+ die "$tranche_name defined in lwlocktranchelist.h but missing from "
+ . "wait_event_names.txt"
+ if $i >= scalar @wait_event_builtin_tranches;
+ die "lists of built-in tranches do not match (first mismatch at "
+ . "$wait_event_builtin_tranches[$i] in wait_event_names.txt and $tranche_name in "
+ . "lwlocktranchelist.h)"
+ if $wait_event_builtin_tranches[$i] ne $tranche_name;
+
+ $i++;
+}
+
+die
+ "$wait_event_builtin_tranches[$i] defined in wait_event_names.txt but missing from "
+ . "lwlocktranchelist.h"
+ if $i < scalar @wait_event_builtin_tranches;
+
print $h "\n";
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;
diff --git a/src/include/storage/meson.build b/src/include/storage/meson.build
index 1e0f5080727..c2d95befd1b 100644
--- a/src/include/storage/meson.build
+++ b/src/include/storage/meson.build
@@ -3,6 +3,7 @@
lwlocknames_h = custom_target('lwlocknames_h',
input: files(
'../../include/storage/lwlocklist.h',
+ '../../include/storage/lwlocktranchelist.h',
'../../backend/utils/activity/wait_event_names.txt'),
output: ['lwlocknames.h'],
command: [
--
2.34.1
On Fri, Jul 18, 2025 at 01:39:15PM +0000, Bertrand Drouvot wrote:
0002 - While doing changes in generate-lwlocknames.pl, I noticed that
$continue is not used (Oversight in commit da952b415f4), so let's remove it.
I haven't looked closely at the other patches, but I went ahead and
committed this one to get it out of the way.
--
nathan
On Fri, Jul 18, 2025 at 01:39:15PM +0000, Bertrand Drouvot wrote:
+#define PG_BUILTIN_LWTRANCHE(id, name) [id] = name, +#include "storage/lwlocktranchelist.h" +#undef PG_BUILTIN_LWTRANCHE
Why not reuse PG_LWLOCK for this?
+ # Stop recording if we reach another section. + last if /^Section:/;
Can we add a note to wait_event_names.txt about the required
ordering/matching of the non-predefined LWLocks? Otherwise, these patches
look pretty good to me.
--
nathan
On Mon, Jul 21, 2025 at 03:20:55PM -0500, Nathan Bossart wrote:
On Fri, Jul 18, 2025 at 01:39:15PM +0000, Bertrand Drouvot wrote:
+#define PG_BUILTIN_LWTRANCHE(id, name) [id] = name, +#include "storage/lwlocktranchelist.h" +#undef PG_BUILTIN_LWTRANCHEWhy not reuse PG_LWLOCK for this?
+ # Stop recording if we reach another section. + last if /^Section:/;Can we add a note to wait_event_names.txt about the required
ordering/matching of the non-predefined LWLocks? Otherwise, these patches
look pretty good to me.
Something else I just thought of: could we remove the list of built-in
tranches in lwlock.h with some macro magic that generates it from
lwlocktranchelist.h, too?
--
nathan
On Mon, Jul 21, 2025 at 03:28:14PM -0500, Nathan Bossart wrote:
On Mon, Jul 21, 2025 at 03:20:55PM -0500, Nathan Bossart wrote:
Can we add a note to wait_event_names.txt about the required
ordering/matching of the non-predefined LWLocks? Otherwise, these patches
look pretty good to me.Something else I just thought of: could we remove the list of built-in
tranches in lwlock.h with some macro magic that generates it from
lwlocktranchelist.h, too?
Ah, you mean removing the need to have to maintain BuiltinTrancheIds.
This structure depends on NUM_INDIVIDUAL_LWLOCKS for the start value.
Not really an objection per-se, but trying to automate everything may
impact the readability of this area of the code.
--
Michael
On Tue, Jul 22, 2025 at 08:02:52AM +0900, Michael Paquier wrote:
Ah, you mean removing the need to have to maintain BuiltinTrancheIds.
This structure depends on NUM_INDIVIDUAL_LWLOCKS for the start value.
Not really an objection per-se, but trying to automate everything may
impact the readability of this area of the code.
I bet we could maintain a decent level of readability with some extra
commentary. IMHO it's worth it to avoid maintaining duplicate lists. But
that's not something I feel terribly strong about, if others disagree.
FWIW I was imagining something like this:
typedef enum BuiltinTrancheIds
{
LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
#define PG_BUILTIN_LWTRANCHE(id, name) id,
#include "storage/lwlocktranchelist.h"
#undef PG_BUILTIN_LWTRANCHE
LWTRANCHE_FIRST_USER_DEFINED,
} BuiltinTrancheIds;
--
nathan
On Mon, Jul 21, 2025 at 08:34:41PM -0500, Nathan Bossart wrote:
I bet we could maintain a decent level of readability with some extra
commentary. IMHO it's worth it to avoid maintaining duplicate lists. But
that's not something I feel terribly strong about, if others disagree.
FWIW I was imagining something like this:typedef enum BuiltinTrancheIds
{
LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
Something like that would be OK for me.
--
Michael
Hi,
On Mon, Jul 21, 2025 at 03:28:14PM -0500, Nathan Bossart wrote:
On Mon, Jul 21, 2025 at 03:20:55PM -0500, Nathan Bossart wrote:
On Fri, Jul 18, 2025 at 01:39:15PM +0000, Bertrand Drouvot wrote:
+#define PG_BUILTIN_LWTRANCHE(id, name) [id] = name, +#include "storage/lwlocktranchelist.h" +#undef PG_BUILTIN_LWTRANCHEWhy not reuse PG_LWLOCK for this?
+ # Stop recording if we reach another section. + last if /^Section:/;Can we add a note to wait_event_names.txt about the required
ordering/matching of the non-predefined LWLocks? Otherwise, these patches
look pretty good to me.Something else I just thought of: could we remove the list of built-in
tranches in lwlock.h with some macro magic that generates it from
lwlocktranchelist.h, too?
Thanks for looking at the patch series!
Yeah, I also had in mind to auto-generate this enum list (see last sentence
in the initial email [1]/messages/by-id/aHpOgwuFQfcFMZ/B@ip-10-97-1-34.eu-west-3.compute.internal) but did not think that much on how to do it and was
waiting for this patch series to go in before looking at it.
But as I like your macro idea and as you mentioned it here too, then let's do
it now: it's done in 0003 attached.
[1]: /messages/by-id/aHpOgwuFQfcFMZ/B@ip-10-97-1-34.eu-west-3.compute.internal
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
Attachments:
v2-0001-Create-lwlocktranchelist.h.patchtext/x-diff; charset=us-asciiDownload
From c6b491e192048df9f350047040229c42f2409f61 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Fri, 18 Jul 2025 10:03:18 +0000
Subject: [PATCH v2 1/3] Create lwlocktranchelist.h
This commit extracts the predefined LWLocks tranches from lwlock.c and puts them
in a new file (namely lwlocktranchelist.h).
This way, we can include this file in lwlock.c using the same macro pattern
as we do for lwlocklist.h.
This gives us the chance to cross-check with wait_event_names.txt in
generate-lwlocknames.pl in a following commit.
---
src/backend/storage/lmgr/lwlock.c | 47 ++--------------
src/include/storage/lwlocktranchelist.h | 72 +++++++++++++++++++++++++
src/tools/pginclude/headerscheck | 1 +
3 files changed, 78 insertions(+), 42 deletions(-)
create mode 100644 src/include/storage/lwlocktranchelist.h
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 2d43bf2cc13..d20750c9f2f 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -124,7 +124,7 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
*
* 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.
+ * appear in lwlocktranchelist.h.
*
* 3. Extensions can create new tranches, via either RequestNamedLWLockTranche
* or LWLockRegisterTranche. The names of these that are known in the current
@@ -137,47 +137,10 @@ static const char *const BuiltinTrancheNames[] = {
#define PG_LWLOCK(id, lockname) [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",
+
+#define PG_LWLOCK(id, name) [id] = name,
+#include "storage/lwlocktranchelist.h"
+#undef PG_LWLOCK
};
StaticAssertDecl(lengthof(BuiltinTrancheNames) ==
diff --git a/src/include/storage/lwlocktranchelist.h b/src/include/storage/lwlocktranchelist.h
new file mode 100644
index 00000000000..973be80369f
--- /dev/null
+++ b/src/include/storage/lwlocktranchelist.h
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * lwlocktranchelist.h
+ *
+ * The predefined built-in LWLock tranche list is kept in its own source
+ * file for use by automatic tools. The exact representation of a tranche
+ * is determined by the PG_LWLOCK macro, which is not defined in
+ * this file; it can be defined by the caller for special purposes.
+ *
+ * Also, generate-lwlocknames.pl processes this file for validation against
+ * wait_event_names.txt.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/include/storage/lwlocktranchelist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * Predefined tranches for built-in groups of locks.
+ *
+ * If you add a tranche, do not forget to update the section WaitEventLWLock of
+ * wait_event_names.txt.
+ *
+ * Note that the tranche names here should match exactly what appears
+ * in wait_event_names.txt.
+ */
+
+PG_LWLOCK(LWTRANCHE_XACT_BUFFER, "XactBuffer")
+PG_LWLOCK(LWTRANCHE_COMMITTS_BUFFER, "CommitTsBuffer")
+PG_LWLOCK(LWTRANCHE_SUBTRANS_BUFFER, "SubtransBuffer")
+PG_LWLOCK(LWTRANCHE_MULTIXACTOFFSET_BUFFER, "MultiXactOffsetBuffer")
+PG_LWLOCK(LWTRANCHE_MULTIXACTMEMBER_BUFFER, "MultiXactMemberBuffer")
+PG_LWLOCK(LWTRANCHE_NOTIFY_BUFFER, "NotifyBuffer")
+PG_LWLOCK(LWTRANCHE_SERIAL_BUFFER, "SerialBuffer")
+PG_LWLOCK(LWTRANCHE_WAL_INSERT, "WALInsert")
+PG_LWLOCK(LWTRANCHE_BUFFER_CONTENT, "BufferContent")
+PG_LWLOCK(LWTRANCHE_REPLICATION_ORIGIN_STATE, "ReplicationOriginState")
+PG_LWLOCK(LWTRANCHE_REPLICATION_SLOT_IO, "ReplicationSlotIO")
+PG_LWLOCK(LWTRANCHE_LOCK_FASTPATH, "LockFastPath")
+PG_LWLOCK(LWTRANCHE_BUFFER_MAPPING, "BufferMapping")
+PG_LWLOCK(LWTRANCHE_LOCK_MANAGER, "LockManager")
+PG_LWLOCK(LWTRANCHE_PREDICATE_LOCK_MANAGER, "PredicateLockManager")
+PG_LWLOCK(LWTRANCHE_PARALLEL_HASH_JOIN, "ParallelHashJoin")
+PG_LWLOCK(LWTRANCHE_PARALLEL_BTREE_SCAN, "ParallelBtreeScan")
+PG_LWLOCK(LWTRANCHE_PARALLEL_QUERY_DSA, "ParallelQueryDSA")
+PG_LWLOCK(LWTRANCHE_PER_SESSION_DSA, "PerSessionDSA")
+PG_LWLOCK(LWTRANCHE_PER_SESSION_RECORD_TYPE, "PerSessionRecordType")
+PG_LWLOCK(LWTRANCHE_PER_SESSION_RECORD_TYPMOD, "PerSessionRecordTypmod")
+PG_LWLOCK(LWTRANCHE_SHARED_TUPLESTORE, "SharedTupleStore")
+PG_LWLOCK(LWTRANCHE_SHARED_TIDBITMAP, "SharedTidBitmap")
+PG_LWLOCK(LWTRANCHE_PARALLEL_APPEND, "ParallelAppend")
+PG_LWLOCK(LWTRANCHE_PER_XACT_PREDICATE_LIST, "PerXactPredicateList")
+PG_LWLOCK(LWTRANCHE_PGSTATS_DSA, "PgStatsDSA")
+PG_LWLOCK(LWTRANCHE_PGSTATS_HASH, "PgStatsHash")
+PG_LWLOCK(LWTRANCHE_PGSTATS_DATA, "PgStatsData")
+PG_LWLOCK(LWTRANCHE_LAUNCHER_DSA, "LogicalRepLauncherDSA")
+PG_LWLOCK(LWTRANCHE_LAUNCHER_HASH, "LogicalRepLauncherHash")
+PG_LWLOCK(LWTRANCHE_DSM_REGISTRY_DSA, "DSMRegistryDSA")
+PG_LWLOCK(LWTRANCHE_DSM_REGISTRY_HASH, "DSMRegistryHash")
+PG_LWLOCK(LWTRANCHE_COMMITTS_SLRU, "CommitTsSLRU")
+PG_LWLOCK(LWTRANCHE_MULTIXACTOFFSET_SLRU, "MultiXactOffsetSLRU")
+PG_LWLOCK(LWTRANCHE_MULTIXACTMEMBER_SLRU, "MultiXactMemberSLRU")
+PG_LWLOCK(LWTRANCHE_NOTIFY_SLRU, "NotifySLRU")
+PG_LWLOCK(LWTRANCHE_SERIAL_SLRU, "SerialSLRU")
+PG_LWLOCK(LWTRANCHE_SUBTRANS_SLRU, "SubtransSLRU")
+PG_LWLOCK(LWTRANCHE_XACT_SLRU, "XactSLRU")
+PG_LWLOCK(LWTRANCHE_PARALLEL_VACUUM_DSA, "ParallelVacuumDSA")
+PG_LWLOCK(LWTRANCHE_AIO_URING_COMPLETION, "AioUringCompletion")
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 9e86d049362..4dc5bfab995 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -132,6 +132,7 @@ do
test "$f" = src/interfaces/ecpg/preproc/ecpg_kwlist.h && continue
test "$f" = src/include/regex/regerrs.h && continue
test "$f" = src/include/storage/lwlocklist.h && continue
+ test "$f" = src/include/storage/lwlocktranchelist.h && continue
test "$f" = src/include/tcop/cmdtaglist.h && continue
test "$f" = src/pl/plpgsql/src/plerrcodes.h && continue
test "$f" = src/pl/plpython/spiexceptions.h && continue
--
2.34.1
v2-0002-Cross-check-lists-of-predefined-tranches.patchtext/x-diff; charset=us-asciiDownload
From 8e81efa74f05783b663dabf466b1880c517f2ad4 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Fri, 18 Jul 2025 11:19:19 +0000
Subject: [PATCH v2 2/3] Cross-check lists of predefined tranches.
Both builtin_lwlocktranchelist.h and wait_event_names.txt contain a list of all
the predefined tranches. It is easy to miss one or the other (see a493e741d32
,08b9b9e043b and c3623703f36).
This commit adds a cross-check of these lists to the script that already does
the same cross-check for lwlocklist.h.
If the lists do not match exactly, building will fail (same as in 5b1b9bce844).
---
src/backend/Makefile | 2 +-
src/backend/storage/lmgr/Makefile | 2 +-
.../storage/lmgr/generate-lwlocknames.pl | 77 +++++++++++++++++--
.../utils/activity/wait_event_names.txt | 4 +-
src/include/storage/meson.build | 1 +
5 files changed, 77 insertions(+), 9 deletions(-)
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 7344c8c7f5c..cda1bbe2b35 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -111,7 +111,7 @@ $(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
parser/gram.h: parser/gram.y
$(MAKE) -C parser gram.h
-storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl ../include/storage/lwlocklist.h utils/activity/wait_event_names.txt
+storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl ../include/storage/lwlocklist.h ../include/storage/lwlocktranchelist.h utils/activity/wait_event_names.txt
$(MAKE) -C storage/lmgr lwlocknames.h
utils/activity/wait_event_types.h: utils/activity/generate-wait_event_types.pl utils/activity/wait_event_names.txt
diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile
index 6cbaf23b855..523804889ae 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -33,7 +33,7 @@ s_lock_test: s_lock.c $(top_builddir)/src/common/libpgcommon.a $(top_builddir)/s
$(TASPATH) -L $(top_builddir)/src/common -lpgcommon \
-L $(top_builddir)/src/port -lpgport -lm -o s_lock_test
-lwlocknames.h: ../../../include/storage/lwlocklist.h ../../utils/activity/wait_event_names.txt generate-lwlocknames.pl
+lwlocknames.h: ../../../include/storage/lwlocklist.h ../../../include/storage/lwlocktranchelist.h ../../utils/activity/wait_event_names.txt generate-lwlocknames.pl
$(PERL) $(srcdir)/generate-lwlocknames.pl $^
check: s_lock_test
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index c7a6720440d..f546d080d7a 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -14,7 +14,8 @@ my $lastlockidx = -1;
GetOptions('outdir:s' => \$output_path);
open my $lwlocklist, '<', $ARGV[0] or die;
-open my $wait_event_names, '<', $ARGV[1] or die;
+open my $builtin_lwtranche_list, '<', $ARGV[1] or die;
+open my $wait_event_names, '<', $ARGV[2] or die;
# Include PID in suffix in case parallel make runs this multiple times.
my $htmp = "$output_path/lwlocknames.h.tmp$$";
@@ -27,18 +28,25 @@ 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
+# and in lwlocktranchelist.h.
#
+my @wait_event_builtin_tranches;
my @wait_event_lwlocks;
my $record_lwlocks = 0;
+my $in_builtin_tranches = 0;
while (<$wait_event_names>)
{
chomp;
- # Check for end marker.
- last if /^# END OF PREDEFINED LWLOCKS/;
+ # Check for predefined end marker.
+ if (/^# END OF PREDEFINED LWLOCKS/)
+ {
+ $in_builtin_tranches = 1;
+ next;
+ }
# Skip comments and empty lines.
next if /^#/;
@@ -54,9 +62,20 @@ 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_builtin_tranches)
+ {
+ push(@wait_event_builtin_tranches, $waiteventname);
+ }
+ else
+ {
+ push(@wait_event_lwlocks, $waiteventname);
+ }
}
my $in_comment = 0;
@@ -114,6 +133,52 @@ die
. "lwlocklist.h"
if $i < scalar @wait_event_lwlocks;
+$in_comment = 0;
+$i = 0;
+
+# Cross-check the built-in tranches in lwlocktranchelist.h with
+# wait_event_names.txt.
+while (<$builtin_lwtranche_list>)
+{
+ chomp;
+
+ # Skip single-line C comments and empty lines
+ next if m{^\s*/\*.*\*/$};
+ next if /^\s*$/;
+
+ # skip multiline C comments
+ if ($in_comment == 1)
+ {
+ $in_comment = 0 if m{\*/};
+ next;
+ }
+ elsif (m{^\s*/\*})
+ {
+ $in_comment = 1;
+ next;
+ }
+
+ die "unable to parse lwlocktranchelist.h line \"$_\""
+ unless /^PG_LWLOCK\((\w+),\s*"([^"]+)"\)$/;
+
+ my ($tranche_id, $tranche_name) = ($1, $2);
+
+ die "$tranche_name defined in lwlocktranchelist.h but missing from "
+ . "wait_event_names.txt"
+ if $i >= scalar @wait_event_builtin_tranches;
+ die "lists of built-in tranches do not match (first mismatch at "
+ . "$wait_event_builtin_tranches[$i] in wait_event_names.txt and $tranche_name in "
+ . "lwlocktranchelist.h)"
+ if $wait_event_builtin_tranches[$i] ne $tranche_name;
+
+ $i++;
+}
+
+die
+ "$wait_event_builtin_tranches[$i] defined in wait_event_names.txt but missing from "
+ . "lwlocktranchelist.h"
+ if $i < scalar @wait_event_builtin_tranches;
+
print $h "\n";
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 4da68312b5f..050f94fc56e 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -358,7 +358,9 @@ AioWorkerSubmissionQueue "Waiting to access AIO worker submission queue."
#
# 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.
+# lwlocknames.h. Other LWLocks (i.e., those declared in lwlocktranchelist.h)
+# must be listed in the section below and must be listed in the same order as in
+# lwlocktranchelist.h.
#
XactBuffer "Waiting for I/O on a transaction status SLRU buffer."
diff --git a/src/include/storage/meson.build b/src/include/storage/meson.build
index 1e0f5080727..c2d95befd1b 100644
--- a/src/include/storage/meson.build
+++ b/src/include/storage/meson.build
@@ -3,6 +3,7 @@
lwlocknames_h = custom_target('lwlocknames_h',
input: files(
'../../include/storage/lwlocklist.h',
+ '../../include/storage/lwlocktranchelist.h',
'../../backend/utils/activity/wait_event_names.txt'),
output: ['lwlocknames.h'],
command: [
--
2.34.1
v2-0003-Remove-the-list-of-built-in-tranches-in-lwlock.h.patchtext/x-diff; charset=us-asciiDownload
From 373218a00af09f1e87020b752064fe2fe429a749 Mon Sep 17 00:00:00 2001
From: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Date: Tue, 22 Jul 2025 05:32:55 +0000
Subject: [PATCH v2 3/3] Remove the list of built-in tranches in lwlock.h
Now that commit XXXX extracted the predefined LWLock tranches from lwlock.c and
put them in a new file (namely lwlocktranchelist.h), we can remove the hard-coded
list of built-in tranches in lwlock.h and rely on lwlocktranchelist.h
instead.
---
src/include/storage/lwlock.h | 48 +++++-------------------------------
1 file changed, 6 insertions(+), 42 deletions(-)
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 08a72569ae5..04e0823451e 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -176,51 +176,15 @@ extern void LWLockInitialize(LWLock *lock, int tranche_id);
* Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
* we reserve additional tranche IDs for builtin tranches not included in
* the set of individual LWLocks. A call to LWLockNewTrancheId will never
- * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED. The enum list source
+ * of truth is in lwlocktranchelist.h.
*/
typedef enum BuiltinTrancheIds
{
- LWTRANCHE_XACT_BUFFER = NUM_INDIVIDUAL_LWLOCKS,
- LWTRANCHE_COMMITTS_BUFFER,
- LWTRANCHE_SUBTRANS_BUFFER,
- LWTRANCHE_MULTIXACTOFFSET_BUFFER,
- LWTRANCHE_MULTIXACTMEMBER_BUFFER,
- LWTRANCHE_NOTIFY_BUFFER,
- LWTRANCHE_SERIAL_BUFFER,
- LWTRANCHE_WAL_INSERT,
- LWTRANCHE_BUFFER_CONTENT,
- LWTRANCHE_REPLICATION_ORIGIN_STATE,
- LWTRANCHE_REPLICATION_SLOT_IO,
- LWTRANCHE_LOCK_FASTPATH,
- LWTRANCHE_BUFFER_MAPPING,
- LWTRANCHE_LOCK_MANAGER,
- LWTRANCHE_PREDICATE_LOCK_MANAGER,
- LWTRANCHE_PARALLEL_HASH_JOIN,
- LWTRANCHE_PARALLEL_BTREE_SCAN,
- LWTRANCHE_PARALLEL_QUERY_DSA,
- LWTRANCHE_PER_SESSION_DSA,
- LWTRANCHE_PER_SESSION_RECORD_TYPE,
- LWTRANCHE_PER_SESSION_RECORD_TYPMOD,
- LWTRANCHE_SHARED_TUPLESTORE,
- LWTRANCHE_SHARED_TIDBITMAP,
- LWTRANCHE_PARALLEL_APPEND,
- LWTRANCHE_PER_XACT_PREDICATE_LIST,
- LWTRANCHE_PGSTATS_DSA,
- LWTRANCHE_PGSTATS_HASH,
- LWTRANCHE_PGSTATS_DATA,
- LWTRANCHE_LAUNCHER_DSA,
- LWTRANCHE_LAUNCHER_HASH,
- LWTRANCHE_DSM_REGISTRY_DSA,
- LWTRANCHE_DSM_REGISTRY_HASH,
- LWTRANCHE_COMMITTS_SLRU,
- LWTRANCHE_MULTIXACTMEMBER_SLRU,
- LWTRANCHE_MULTIXACTOFFSET_SLRU,
- LWTRANCHE_NOTIFY_SLRU,
- LWTRANCHE_SERIAL_SLRU,
- LWTRANCHE_SUBTRANS_SLRU,
- LWTRANCHE_XACT_SLRU,
- LWTRANCHE_PARALLEL_VACUUM_DSA,
- LWTRANCHE_AIO_URING_COMPLETION,
+ LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
+#define PG_LWLOCK(id, name) id,
+#include "storage/lwlocktranchelist.h"
+#undef PG_LWLOCK
LWTRANCHE_FIRST_USER_DEFINED,
} BuiltinTrancheIds;
--
2.34.1
Hi,
On Mon, Jul 21, 2025 at 03:20:55PM -0500, Nathan Bossart wrote:
On Fri, Jul 18, 2025 at 01:39:15PM +0000, Bertrand Drouvot wrote:
+#define PG_BUILTIN_LWTRANCHE(id, name) [id] = name, +#include "storage/lwlocktranchelist.h" +#undef PG_BUILTIN_LWTRANCHEWhy not reuse PG_LWLOCK for this?
I was not sure we'd want add a new file or add those in lwlocklist.h (in which
case 2 macros would have been simpler). As it looks like we are going with a
new file then yeah we can reuse PG_LWLOCK: done in v2 just shared up-thread.
+ # Stop recording if we reach another section. + last if /^Section:/;Can we add a note to wait_event_names.txt about the required
ordering/matching of the non-predefined LWLocks?
Sure, done in v2 too.
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
On Tue, Jul 22, 2025 at 06:23:50AM +0000, Bertrand Drouvot wrote:
Sure, done in v2 too.
I stared at this patch some more and came up with the attached. The
biggest change is that I've moved the list of built-in LWLock tranches to
the existing lwlocklist.h file. That simplifies the patch and centralizes
these lists. This is arguably a bit too much preprocessor magic, though.
Thoughts?
--
nathan
Attachments:
v3-0001-Cross-check-lists-of-built-in-LWLock-tranches.patchtext/plain; charset=us-asciiDownload
From f354557d14d9a384404b8ba6f1e492132bb2b59f Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Tue, 22 Jul 2025 14:13:11 -0500
Subject: [PATCH v3 1/1] Cross check lists of built-in LWLock tranches.
---
.../storage/lmgr/generate-lwlocknames.pl | 77 ++++++++++++++++++-
src/backend/storage/lmgr/lwlock.c | 48 +-----------
.../utils/activity/wait_event_names.txt | 10 ++-
src/include/storage/lwlock.h | 56 ++++----------
src/include/storage/lwlocklist.h | 57 +++++++++++++-
5 files changed, 152 insertions(+), 96 deletions(-)
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index c7a6720440d..039c6386cfe 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -5,6 +5,7 @@
use strict;
use warnings FATAL => 'all';
+use Fcntl ':seek';
use Getopt::Long;
my $output_path = '.';
@@ -27,18 +28,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,11 +61,23 @@ 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);
+ }
}
+# Cross-check list of predefined LWLocks with their wait events.
my $in_comment = 0;
my $i = 0;
while (<$lwlocklist>)
@@ -81,6 +100,9 @@ while (<$lwlocklist>)
next;
}
+ # Built-in tranches should be listed below predefined LWLocks.
+ last if /^PG_LWLOCKTRANCHE\((\w+),\s+(\w+)\)$/;
+
die "unable to parse lwlocklist.h line \"$_\""
unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/;
@@ -114,6 +136,53 @@ die
. "lwlocklist.h"
if $i < scalar @wait_event_lwlocks;
+# Cross-check list of built-in LWLock tranches with their wait events.
+$in_comment = 0;
+$i = 0;
+seek $lwlocklist, 0, 0;
+while (<$lwlocklist>)
+{
+ chomp;
+
+ # Skip single-line C comments and empty lines
+ next if m{^\s*/\*.*\*/$};
+ next if /^\s*$/;
+
+ # skip multiline C comments
+ if ($in_comment == 1)
+ {
+ $in_comment = 0 if m{\*/};
+ next;
+ }
+ elsif (m{^\s*/\*})
+ {
+ $in_comment = 1;
+ next;
+ }
+
+ # Built-in LWLock tranches should be listed below predefined LWLocks.
+ next if /^PG_LWLOCK\((\w+),\s+(\w+)\)$/;
+
+ die "unable to parse lwlocklist.h line \"$_\""
+ unless /^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 $i >= scalar @wait_event_tranches;
+ die "lists of built-in LWLock tranches do not match (first mismatch at "
+ . "$wait_event_tranches[$i] in wait_event_names.txt and $tranche_name "
+ . "in lwlocklist.h)"
+ if $wait_event_tranches[$i] ne $tranche_name;
+ $i++;
+}
+
+die
+ "$wait_event_tranches[$i] defined in wait_event_names.txt but missing from "
+ . "lwlocklist.h"
+ if $i < scalar @wait_event_tranches;
+
print $h "\n";
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 2d43bf2cc13..ec9c345ffdf 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -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) ==
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 4da68312b5f..0be307d2ca0 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -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."
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 08a72569ae5..5e717765764 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -176,51 +176,23 @@ extern void LWLockInitialize(LWLock *lock, int tranche_id);
* Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
* we reserve additional tranche IDs for builtin tranches not included in
* the set of individual LWLocks. A call to LWLockNewTrancheId will never
- * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED. The actual list of
+ * built-in tranches is kept in lwlocklist.h.
*/
typedef enum BuiltinTrancheIds
{
- LWTRANCHE_XACT_BUFFER = NUM_INDIVIDUAL_LWLOCKS,
- LWTRANCHE_COMMITTS_BUFFER,
- LWTRANCHE_SUBTRANS_BUFFER,
- LWTRANCHE_MULTIXACTOFFSET_BUFFER,
- LWTRANCHE_MULTIXACTMEMBER_BUFFER,
- LWTRANCHE_NOTIFY_BUFFER,
- LWTRANCHE_SERIAL_BUFFER,
- LWTRANCHE_WAL_INSERT,
- LWTRANCHE_BUFFER_CONTENT,
- LWTRANCHE_REPLICATION_ORIGIN_STATE,
- LWTRANCHE_REPLICATION_SLOT_IO,
- LWTRANCHE_LOCK_FASTPATH,
- LWTRANCHE_BUFFER_MAPPING,
- LWTRANCHE_LOCK_MANAGER,
- LWTRANCHE_PREDICATE_LOCK_MANAGER,
- LWTRANCHE_PARALLEL_HASH_JOIN,
- LWTRANCHE_PARALLEL_BTREE_SCAN,
- LWTRANCHE_PARALLEL_QUERY_DSA,
- LWTRANCHE_PER_SESSION_DSA,
- LWTRANCHE_PER_SESSION_RECORD_TYPE,
- LWTRANCHE_PER_SESSION_RECORD_TYPMOD,
- LWTRANCHE_SHARED_TUPLESTORE,
- LWTRANCHE_SHARED_TIDBITMAP,
- LWTRANCHE_PARALLEL_APPEND,
- LWTRANCHE_PER_XACT_PREDICATE_LIST,
- LWTRANCHE_PGSTATS_DSA,
- LWTRANCHE_PGSTATS_HASH,
- LWTRANCHE_PGSTATS_DATA,
- LWTRANCHE_LAUNCHER_DSA,
- LWTRANCHE_LAUNCHER_HASH,
- LWTRANCHE_DSM_REGISTRY_DSA,
- LWTRANCHE_DSM_REGISTRY_HASH,
- LWTRANCHE_COMMITTS_SLRU,
- LWTRANCHE_MULTIXACTMEMBER_SLRU,
- LWTRANCHE_MULTIXACTOFFSET_SLRU,
- LWTRANCHE_NOTIFY_SLRU,
- LWTRANCHE_SERIAL_SLRU,
- LWTRANCHE_SUBTRANS_SLRU,
- LWTRANCHE_XACT_SLRU,
- LWTRANCHE_PARALLEL_VACUUM_DSA,
- LWTRANCHE_AIO_URING_COMPLETION,
+ /*
+ * LWTRANCHE_INVALID is an unused value that only exists to initialize the
+ * rest of the tranches to appropriate values.
+ */
+ LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
+
+#define PG_LWLOCK(id, name)
+#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
+#include "storage/lwlocklist.h"
+#undef PG_LWLOCK
+#undef PG_LWLOCKTRANCHE
+
LWTRANCHE_FIRST_USER_DEFINED,
} BuiltinTrancheIds;
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index a9681738146..208d2e3a8ed 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -2,9 +2,10 @@
*
* lwlocklist.h
*
- * The predefined LWLock list is kept in its own source file for use by
- * automatic tools. The exact representation of a keyword is determined by
- * the PG_LWLOCK macro, which is not defined in this file; it can be
+ * The list of predefined LWLocks and built-in LWLock tranches is kept in
+ * its own source file for use by automatic tools. The exact
+ * representation of a keyword is determined by the PG_LWLOCK and
+ * PG_LWLOCKTRANCHE macros, which are not defined in this file; they can be
* defined by the caller for special purposes.
*
* Also, generate-lwlocknames.pl processes this file to create lwlocknames.h.
@@ -84,3 +85,53 @@ PG_LWLOCK(50, DSMRegistry)
PG_LWLOCK(51, InjectionPoint)
PG_LWLOCK(52, SerialControl)
PG_LWLOCK(53, AioWorkerSubmissionQueue)
+
+/*
+ * There also exist several built-in LWLock tranches. As with the predefined
+ * LWLocks, be sure to update the WaitEventLWLock section of
+ * src/backend/utils/activity/wait_event_names.txt when modifying this list.
+ *
+ * Note that the IDs here (the first value) don't include the LWTRANCHE_
+ * prefix. It's added elsewhere.
+ */
+PG_LWLOCKTRANCHE(XACT_BUFFER, XactBuffer)
+PG_LWLOCKTRANCHE(COMMITTS_BUFFER, CommitTsBuffer)
+PG_LWLOCKTRANCHE(SUBTRANS_BUFFER, SubtransBuffer)
+PG_LWLOCKTRANCHE(MULTIXACTOFFSET_BUFFER, MultiXactOffsetBuffer)
+PG_LWLOCKTRANCHE(MULTIXACTMEMBER_BUFFER, MultiXactMemberBuffer)
+PG_LWLOCKTRANCHE(NOTIFY_BUFFER, NotifyBuffer)
+PG_LWLOCKTRANCHE(SERIAL_BUFFER, SerialBuffer)
+PG_LWLOCKTRANCHE(WAL_INSERT, WALInsert)
+PG_LWLOCKTRANCHE(BUFFER_CONTENT, BufferContent)
+PG_LWLOCKTRANCHE(REPLICATION_ORIGIN_STATE, ReplicationOriginState)
+PG_LWLOCKTRANCHE(REPLICATION_SLOT_IO, ReplicationSlotIO)
+PG_LWLOCKTRANCHE(LOCK_FASTPATH, LockFastPath)
+PG_LWLOCKTRANCHE(BUFFER_MAPPING, BufferMapping)
+PG_LWLOCKTRANCHE(LOCK_MANAGER, LockManager)
+PG_LWLOCKTRANCHE(PREDICATE_LOCK_MANAGER, PredicateLockManager)
+PG_LWLOCKTRANCHE(PARALLEL_HASH_JOIN, ParallelHashJoin)
+PG_LWLOCKTRANCHE(PARALLEL_BTREE_SCAN, ParallelBtreeScan)
+PG_LWLOCKTRANCHE(PARALLEL_QUERY_DSA, ParallelQueryDSA)
+PG_LWLOCKTRANCHE(PER_SESSION_DSA, PerSessionDSA)
+PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPE, PerSessionRecordType)
+PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPMOD, PerSessionRecordTypmod)
+PG_LWLOCKTRANCHE(SHARED_TUPLESTORE, SharedTupleStore)
+PG_LWLOCKTRANCHE(SHARED_TIDBITMAP, SharedTidBitmap)
+PG_LWLOCKTRANCHE(PARALLEL_APPEND, ParallelAppend)
+PG_LWLOCKTRANCHE(PER_XACT_PREDICATE_LIST, PerXactPredicateList)
+PG_LWLOCKTRANCHE(PGSTATS_DSA, PgStatsDSA)
+PG_LWLOCKTRANCHE(PGSTATS_HASH, PgStatsHash)
+PG_LWLOCKTRANCHE(PGSTATS_DATA, PgStatsData)
+PG_LWLOCKTRANCHE(LAUNCHER_DSA, LogicalRepLauncherDSA)
+PG_LWLOCKTRANCHE(LAUNCHER_HASH, LogicalRepLauncherHash)
+PG_LWLOCKTRANCHE(DSM_REGISTRY_DSA, DSMRegistryDSA)
+PG_LWLOCKTRANCHE(DSM_REGISTRY_HASH, DSMRegistryHash)
+PG_LWLOCKTRANCHE(COMMITTS_SLRU, CommitTsSLRU)
+PG_LWLOCKTRANCHE(MULTIXACTOFFSET_SLRU, MultiXactOffsetSLRU)
+PG_LWLOCKTRANCHE(MULTIXACTMEMBER_SLRU, MultiXactMemberSLRU)
+PG_LWLOCKTRANCHE(NOTIFY_SLRU, NotifySLRU)
+PG_LWLOCKTRANCHE(SERIAL_SLRU, SerialSLRU)
+PG_LWLOCKTRANCHE(SUBTRANS_SLRU, SubtransSLRU)
+PG_LWLOCKTRANCHE(XACT_SLRU, XactSLRU)
+PG_LWLOCKTRANCHE(PARALLEL_VACUUM_DSA, ParallelVacuumDSA)
+PG_LWLOCKTRANCHE(AIO_URING_COMPLETION, AioUringCompletion)
--
2.39.5 (Apple Git-154)
On Tue, Jul 22, 2025 at 02:25:13PM -0500, Nathan Bossart wrote:
I stared at this patch some more and came up with the attached. The
biggest change is that I've moved the list of built-in LWLock tranches to
the existing lwlocklist.h file. That simplifies the patch and centralizes
these lists. This is arguably a bit too much preprocessor magic, though.
Thoughts?
With the argument about checking the consistency of the data between
wait_event_names.txt, that looks like an improvement to me. And as
far as I can see, the check you are adding in generate-lwlocknames.pl
also makes sure that the ordering of the entries is correct.
In short, I side with the argument that this extra magic will save
cycles overall.
--
Michael
Hi,
On Wed, Jul 23, 2025 at 12:23:37PM +0900, Michael Paquier wrote:
On Tue, Jul 22, 2025 at 02:25:13PM -0500, Nathan Bossart wrote:
I stared at this patch some more and came up with the attached. The
biggest change is that I've moved the list of built-in LWLock tranches to
the existing lwlocklist.h file. That simplifies the patch and centralizes
these lists. This is arguably a bit too much preprocessor magic, though.
Yeah, but OTOH we avoid the addition of a new file and we avoid changing some
meson and make files. Also the distinction is still clear as we are using a new
macro name. So that's fine by me.
Thoughts?
I noticed that you removed the LWTRANCHE_ prefix in lwlocklist.h, while I agree
that's not needed, that could be misleading for people that grep for things like
"LWTRANCHE_XACT_BUFFER" for example. I don't think that's a big deal though.
Also, I think we don't need to read lwlocklist.h twice in generate-lwlocknames.pl.
PFA v4 where the only change compared to v3 is that it reads lwlocklist.h once
in generate-lwlocknames.pl.
Regards,
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
Attachments:
v4-0001-Cross-check-lists-of-built-in-LWLock-tranches.patchtext/x-diff; charset=us-asciiDownload
From 56bf036718866eccc04736a36da47968e7b68d9e Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathan@postgresql.org>
Date: Tue, 22 Jul 2025 14:13:11 -0500
Subject: [PATCH v4] Cross check lists of built-in LWLock tranches.
---
.../storage/lmgr/generate-lwlocknames.pl | 103 +++++++++++++-----
src/backend/storage/lmgr/lwlock.c | 48 +-------
.../utils/activity/wait_event_names.txt | 10 +-
src/include/storage/lwlock.h | 56 +++-------
src/include/storage/lwlocklist.h | 57 +++++++++-
5 files changed, 156 insertions(+), 118 deletions(-)
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index c7a6720440d..6bd6175f2e6 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -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,27 @@ 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);
+ }
}
+# Cross-check lists of predefined LWLocks and built-in LWLock tranches with their
+# wait events.
my $in_comment = 0;
-my $i = 0;
+my $lwlock_count = 0;
+my $tranche_count = 0;
while (<$lwlocklist>)
{
chomp;
@@ -81,38 +101,69 @@ while (<$lwlocklist>)
next;
}
- die "unable to parse lwlocklist.h line \"$_\""
- unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/;
+ # Parse PG_LWLOCK entries to cross-check the predefined LWLocks
+ if (/^PG_LWLOCK\((\d+),\s+(\w+)\)$/)
+ {
+ my ($lockidx, $lockname) = ($1, $2);
- (my $lockidx, my $lockname) = ($1, $2);
+ die "lwlocklist.h not in order" if $lockidx < $lastlockidx;
+ die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx;
- 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;
- 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++;
+ $lwlock_count++;
- while ($lastlockidx < $lockidx - 1)
+ 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;
+ }
+
+ # Parse PG_LWLOCKTRANCHE\ entries to cross-check the built-in LWLock tranches
+ if (/^PG_LWLOCKTRANCHE\((\w+),\s+(\w+)\)$/)
{
- ++$lastlockidx;
+ 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;
}
- $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";
+ # If we get here, the line couldn't be parsed
+ die "unable to parse lwlocklist.h line \"$_\"";
}
+# Ensure we found all expected entries
+die
+ "$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_lwlocks[$i] defined in wait_event_names.txt but missing from "
+ "$wait_event_tranches[$tranche_count] defined in wait_event_names.txt but missing from "
. "lwlocklist.h"
- if $i < scalar @wait_event_lwlocks;
+ if $tranche_count < scalar @wait_event_tranches;
print $h "\n";
printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1;
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 2d43bf2cc13..ec9c345ffdf 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -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) ==
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 4da68312b5f..0be307d2ca0 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -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."
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 08a72569ae5..5e717765764 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -176,51 +176,23 @@ extern void LWLockInitialize(LWLock *lock, int tranche_id);
* Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
* we reserve additional tranche IDs for builtin tranches not included in
* the set of individual LWLocks. A call to LWLockNewTrancheId will never
- * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED. The actual list of
+ * built-in tranches is kept in lwlocklist.h.
*/
typedef enum BuiltinTrancheIds
{
- LWTRANCHE_XACT_BUFFER = NUM_INDIVIDUAL_LWLOCKS,
- LWTRANCHE_COMMITTS_BUFFER,
- LWTRANCHE_SUBTRANS_BUFFER,
- LWTRANCHE_MULTIXACTOFFSET_BUFFER,
- LWTRANCHE_MULTIXACTMEMBER_BUFFER,
- LWTRANCHE_NOTIFY_BUFFER,
- LWTRANCHE_SERIAL_BUFFER,
- LWTRANCHE_WAL_INSERT,
- LWTRANCHE_BUFFER_CONTENT,
- LWTRANCHE_REPLICATION_ORIGIN_STATE,
- LWTRANCHE_REPLICATION_SLOT_IO,
- LWTRANCHE_LOCK_FASTPATH,
- LWTRANCHE_BUFFER_MAPPING,
- LWTRANCHE_LOCK_MANAGER,
- LWTRANCHE_PREDICATE_LOCK_MANAGER,
- LWTRANCHE_PARALLEL_HASH_JOIN,
- LWTRANCHE_PARALLEL_BTREE_SCAN,
- LWTRANCHE_PARALLEL_QUERY_DSA,
- LWTRANCHE_PER_SESSION_DSA,
- LWTRANCHE_PER_SESSION_RECORD_TYPE,
- LWTRANCHE_PER_SESSION_RECORD_TYPMOD,
- LWTRANCHE_SHARED_TUPLESTORE,
- LWTRANCHE_SHARED_TIDBITMAP,
- LWTRANCHE_PARALLEL_APPEND,
- LWTRANCHE_PER_XACT_PREDICATE_LIST,
- LWTRANCHE_PGSTATS_DSA,
- LWTRANCHE_PGSTATS_HASH,
- LWTRANCHE_PGSTATS_DATA,
- LWTRANCHE_LAUNCHER_DSA,
- LWTRANCHE_LAUNCHER_HASH,
- LWTRANCHE_DSM_REGISTRY_DSA,
- LWTRANCHE_DSM_REGISTRY_HASH,
- LWTRANCHE_COMMITTS_SLRU,
- LWTRANCHE_MULTIXACTMEMBER_SLRU,
- LWTRANCHE_MULTIXACTOFFSET_SLRU,
- LWTRANCHE_NOTIFY_SLRU,
- LWTRANCHE_SERIAL_SLRU,
- LWTRANCHE_SUBTRANS_SLRU,
- LWTRANCHE_XACT_SLRU,
- LWTRANCHE_PARALLEL_VACUUM_DSA,
- LWTRANCHE_AIO_URING_COMPLETION,
+ /*
+ * LWTRANCHE_INVALID is an unused value that only exists to initialize the
+ * rest of the tranches to appropriate values.
+ */
+ LWTRANCHE_INVALID = NUM_INDIVIDUAL_LWLOCKS - 1,
+
+#define PG_LWLOCK(id, name)
+#define PG_LWLOCKTRANCHE(id, name) LWTRANCHE_##id,
+#include "storage/lwlocklist.h"
+#undef PG_LWLOCK
+#undef PG_LWLOCKTRANCHE
+
LWTRANCHE_FIRST_USER_DEFINED,
} BuiltinTrancheIds;
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index a9681738146..208d2e3a8ed 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -2,9 +2,10 @@
*
* lwlocklist.h
*
- * The predefined LWLock list is kept in its own source file for use by
- * automatic tools. The exact representation of a keyword is determined by
- * the PG_LWLOCK macro, which is not defined in this file; it can be
+ * The list of predefined LWLocks and built-in LWLock tranches is kept in
+ * its own source file for use by automatic tools. The exact
+ * representation of a keyword is determined by the PG_LWLOCK and
+ * PG_LWLOCKTRANCHE macros, which are not defined in this file; they can be
* defined by the caller for special purposes.
*
* Also, generate-lwlocknames.pl processes this file to create lwlocknames.h.
@@ -84,3 +85,53 @@ PG_LWLOCK(50, DSMRegistry)
PG_LWLOCK(51, InjectionPoint)
PG_LWLOCK(52, SerialControl)
PG_LWLOCK(53, AioWorkerSubmissionQueue)
+
+/*
+ * There also exist several built-in LWLock tranches. As with the predefined
+ * LWLocks, be sure to update the WaitEventLWLock section of
+ * src/backend/utils/activity/wait_event_names.txt when modifying this list.
+ *
+ * Note that the IDs here (the first value) don't include the LWTRANCHE_
+ * prefix. It's added elsewhere.
+ */
+PG_LWLOCKTRANCHE(XACT_BUFFER, XactBuffer)
+PG_LWLOCKTRANCHE(COMMITTS_BUFFER, CommitTsBuffer)
+PG_LWLOCKTRANCHE(SUBTRANS_BUFFER, SubtransBuffer)
+PG_LWLOCKTRANCHE(MULTIXACTOFFSET_BUFFER, MultiXactOffsetBuffer)
+PG_LWLOCKTRANCHE(MULTIXACTMEMBER_BUFFER, MultiXactMemberBuffer)
+PG_LWLOCKTRANCHE(NOTIFY_BUFFER, NotifyBuffer)
+PG_LWLOCKTRANCHE(SERIAL_BUFFER, SerialBuffer)
+PG_LWLOCKTRANCHE(WAL_INSERT, WALInsert)
+PG_LWLOCKTRANCHE(BUFFER_CONTENT, BufferContent)
+PG_LWLOCKTRANCHE(REPLICATION_ORIGIN_STATE, ReplicationOriginState)
+PG_LWLOCKTRANCHE(REPLICATION_SLOT_IO, ReplicationSlotIO)
+PG_LWLOCKTRANCHE(LOCK_FASTPATH, LockFastPath)
+PG_LWLOCKTRANCHE(BUFFER_MAPPING, BufferMapping)
+PG_LWLOCKTRANCHE(LOCK_MANAGER, LockManager)
+PG_LWLOCKTRANCHE(PREDICATE_LOCK_MANAGER, PredicateLockManager)
+PG_LWLOCKTRANCHE(PARALLEL_HASH_JOIN, ParallelHashJoin)
+PG_LWLOCKTRANCHE(PARALLEL_BTREE_SCAN, ParallelBtreeScan)
+PG_LWLOCKTRANCHE(PARALLEL_QUERY_DSA, ParallelQueryDSA)
+PG_LWLOCKTRANCHE(PER_SESSION_DSA, PerSessionDSA)
+PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPE, PerSessionRecordType)
+PG_LWLOCKTRANCHE(PER_SESSION_RECORD_TYPMOD, PerSessionRecordTypmod)
+PG_LWLOCKTRANCHE(SHARED_TUPLESTORE, SharedTupleStore)
+PG_LWLOCKTRANCHE(SHARED_TIDBITMAP, SharedTidBitmap)
+PG_LWLOCKTRANCHE(PARALLEL_APPEND, ParallelAppend)
+PG_LWLOCKTRANCHE(PER_XACT_PREDICATE_LIST, PerXactPredicateList)
+PG_LWLOCKTRANCHE(PGSTATS_DSA, PgStatsDSA)
+PG_LWLOCKTRANCHE(PGSTATS_HASH, PgStatsHash)
+PG_LWLOCKTRANCHE(PGSTATS_DATA, PgStatsData)
+PG_LWLOCKTRANCHE(LAUNCHER_DSA, LogicalRepLauncherDSA)
+PG_LWLOCKTRANCHE(LAUNCHER_HASH, LogicalRepLauncherHash)
+PG_LWLOCKTRANCHE(DSM_REGISTRY_DSA, DSMRegistryDSA)
+PG_LWLOCKTRANCHE(DSM_REGISTRY_HASH, DSMRegistryHash)
+PG_LWLOCKTRANCHE(COMMITTS_SLRU, CommitTsSLRU)
+PG_LWLOCKTRANCHE(MULTIXACTOFFSET_SLRU, MultiXactOffsetSLRU)
+PG_LWLOCKTRANCHE(MULTIXACTMEMBER_SLRU, MultiXactMemberSLRU)
+PG_LWLOCKTRANCHE(NOTIFY_SLRU, NotifySLRU)
+PG_LWLOCKTRANCHE(SERIAL_SLRU, SerialSLRU)
+PG_LWLOCKTRANCHE(SUBTRANS_SLRU, SubtransSLRU)
+PG_LWLOCKTRANCHE(XACT_SLRU, XactSLRU)
+PG_LWLOCKTRANCHE(PARALLEL_VACUUM_DSA, ParallelVacuumDSA)
+PG_LWLOCKTRANCHE(AIO_URING_COMPLETION, AioUringCompletion)
--
2.34.1