From 6359348fafbefb391aad89e47e5e443eb8ab8e29 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 1 Mar 2024 13:03:10 +0100
Subject: [PATCH v2] Rework lwlocknames.txt to become lwlocklist.h

This saves some code and some space in BuiltinTrancheNames, as foreseen
in commit 74a730631065.

We still have to build lwlocknames.h using Perl code, which initially I
wanted to avoid, but it gives us the chance to cross-check
wait_event_names.txt.

Discussion: https://postgr.es/m/202401231025.gbv4nnte5fmm@alvherre.pgsql
---
 src/backend/Makefile                          |  4 +-
 src/backend/storage/lmgr/.gitignore           |  1 -
 src/backend/storage/lmgr/Makefile             |  9 +-
 .../storage/lmgr/generate-lwlocknames.pl      | 60 ++++++-------
 src/backend/storage/lmgr/lwlock.c             | 15 ++--
 src/backend/storage/lmgr/lwlocknames.txt      | 60 -------------
 src/backend/storage/lmgr/meson.build          |  2 -
 .../utils/activity/wait_event_names.txt       |  8 +-
 src/include/storage/lwlock.h                  |  4 +-
 src/include/storage/lwlocklist.h              | 85 +++++++++++++++++++
 src/include/storage/meson.build               | 12 ++-
 src/tools/pginclude/headerscheck              |  1 +
 12 files changed, 136 insertions(+), 125 deletions(-)
 delete mode 100644 src/backend/storage/lmgr/lwlocknames.txt
 create mode 100644 src/include/storage/lwlocklist.h

diff --git a/src/backend/Makefile b/src/backend/Makefile
index d66e2a4b9f..79a12dfd1e 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -110,8 +110,8 @@ $(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 storage/lmgr/lwlocknames.txt utils/activity/wait_event_names.txt
-	$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
+storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl ../include/storage/lwlocklist.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
 	$(MAKE) -C utils/activity wait_event_types.h pgstat_wait_event.c wait_event_funcs_data.c
diff --git a/src/backend/storage/lmgr/.gitignore b/src/backend/storage/lmgr/.gitignore
index dab4c3f580..8e5b734f15 100644
--- a/src/backend/storage/lmgr/.gitignore
+++ b/src/backend/storage/lmgr/.gitignore
@@ -1,3 +1,2 @@
-/lwlocknames.c
 /lwlocknames.h
 /s_lock_test
diff --git a/src/backend/storage/lmgr/Makefile b/src/backend/storage/lmgr/Makefile
index 1aef423384..3f89548bde 100644
--- a/src/backend/storage/lmgr/Makefile
+++ b/src/backend/storage/lmgr/Makefile
@@ -18,7 +18,6 @@ OBJS = \
 	lmgr.o \
 	lock.o \
 	lwlock.o \
-	lwlocknames.o \
 	predicate.o \
 	proc.o \
 	s_lock.o \
@@ -35,11 +34,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
 
-# see notes in src/backend/parser/Makefile
-lwlocknames.c: lwlocknames.h
-	touch $@
-
-lwlocknames.h: $(top_srcdir)/src/backend/storage/lmgr/lwlocknames.txt $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt generate-lwlocknames.pl
+lwlocknames.h: ../../../include/storage/lwlocklist.h ../../utils/activity/wait_event_names.txt generate-lwlocknames.pl
 	$(PERL) $(srcdir)/generate-lwlocknames.pl $^
 
 check: s_lock_test
@@ -47,4 +42,4 @@ check: s_lock_test
 
 clean:
 	rm -f s_lock_test
-	rm -f lwlocknames.h lwlocknames.c
+	rm -f lwlocknames.h
diff --git a/src/backend/storage/lmgr/generate-lwlocknames.pl b/src/backend/storage/lmgr/generate-lwlocknames.pl
index 7b93ecf6c1..eaddd9d3b9 100644
--- a/src/backend/storage/lmgr/generate-lwlocknames.pl
+++ b/src/backend/storage/lmgr/generate-lwlocknames.pl
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 #
-# Generate lwlocknames.h and lwlocknames.c from lwlocknames.txt
+# Generate lwlocknames.h from lwlocklist.h
 # Copyright (c) 2000-2024, PostgreSQL Global Development Group
 
 use strict;
@@ -14,26 +14,22 @@ my $continue = "\n";
 
 GetOptions('outdir:s' => \$output_path);
 
-open my $lwlocknames, '<', $ARGV[0] or die;
+open my $lwlocklist, '<', $ARGV[0] or die;
 open my $wait_event_names, '<', $ARGV[1] or die;
 
 # Include PID in suffix in case parallel make runs this multiple times.
 my $htmp = "$output_path/lwlocknames.h.tmp$$";
-my $ctmp = "$output_path/lwlocknames.c.tmp$$";
 open my $h, '>', $htmp or die "Could not open $htmp: $!";
-open my $c, '>', $ctmp or die "Could not open $ctmp: $!";
 
 my $autogen =
-  "/* autogenerated from src/backend/storage/lmgr/lwlocknames.txt, do not edit */\n";
+  "/* autogenerated from src/include/storage/lwlocklist.h, do not edit */\n";
 print $h $autogen;
 print $h "/* there is deliberately not an #ifndef LWLOCKNAMES_H here */\n\n";
-print $c $autogen, "\n";
 
-print $c "const char *const IndividualLWLockNames[] = {";
 
 #
 # First, record the predefined LWLocks listed in wait_event_names.txt.  We'll
-# cross-check those with the ones in lwlocknames.txt.
+# cross-check those with the ones in lwlocklist.h.
 #
 my @wait_event_lwlocks;
 my $record_lwlocks = 0;
@@ -61,66 +57,70 @@ while (<$wait_event_names>)
 
 	# Record the LWLock.
 	(my $waiteventname, my $waitevendocsentence) = split(/\t/, $_);
-	push(@wait_event_lwlocks, $waiteventname . "Lock");
+	push(@wait_event_lwlocks, $waiteventname);
 }
 
+my $in_comment = 0;
 my $i = 0;
-while (<$lwlocknames>)
+while (<$lwlocklist>)
 {
 	chomp;
 
-	# Skip comments
-	next if /^#/;
+	# Skip single-line C comments and empty lines
+	next if m{^\s*/\*.*\*/$};
 	next if /^\s*$/;
 
-	die "unable to parse lwlocknames.txt"
-	  unless /^(\w+)\s+(\d+)$/;
+	# skip multiline C comments
+	if ($in_comment == 1)
+	{
+		$in_comment = 0 if m{\*/};
+		next;
+	}
+	elsif (m{^\s*/\*})
+	{
+		$in_comment = 1;
+		next;
+	}
 
-	(my $lockname, my $lockidx) = ($1, $2);
+	die "unable to parse lwlocklist.h line \"$_\""
+	  unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/;
 
-	my $trimmedlockname = $lockname;
-	$trimmedlockname =~ s/Lock$//;
-	die "lock names must end with 'Lock'" if $trimmedlockname eq $lockname;
+	(my $lockidx, my $lockname) = ($1, $2);
 
-	die "lwlocknames.txt not in order" if $lockidx < $lastlockidx;
-	die "lwlocknames.txt 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 lwlocknames.txt but missing from "
+	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 "
-	  . "lwlocknames.txt)"
+	  . "lwlocklist.h)"
 	  if $wait_event_lwlocks[$i] ne $lockname;
 	$i++;
 
 	while ($lastlockidx < $lockidx - 1)
 	{
 		++$lastlockidx;
-		printf $c "%s	\"<unassigned:%d>\"", $continue, $lastlockidx;
 		$continue = ",\n";
 	}
-	printf $c "%s	\"%s\"", $continue, $trimmedlockname;
 	$lastlockidx = $lockidx;
 	$continue = ",\n";
 
-	print $h "#define $lockname (&MainLWLockArray[$lockidx].lock)\n";
+	print $h "#define ${lockname}Lock (&MainLWLockArray[$lockidx].lock)\n";
 }
 
 die
   "$wait_event_lwlocks[$i] defined in wait_event_names.txt but missing from "
-  . "lwlocknames.txt"
+  . "lwlocklist.h"
   if $i < scalar @wait_event_lwlocks;
 
-printf $c "\n};\n";
 print $h "\n";
 printf $h "#define NUM_INDIVIDUAL_LWLOCKS		%s\n", $lastlockidx + 1;
 
 close $h;
-close $c;
 
 rename($htmp, "$output_path/lwlocknames.h")
   || die "rename: $htmp to $output_path/lwlocknames.h: $!";
-rename($ctmp, "$output_path/lwlocknames.c") || die "rename: $ctmp: $!";
 
-close $lwlocknames;
+close $lwlocklist;
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index 30f3a09a4c..83992725de 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -112,8 +112,8 @@ StaticAssertDecl(LW_VAL_EXCLUSIVE > (uint32) MAX_BACKENDS,
  * There are three sorts of LWLock "tranches":
  *
  * 1. The individually-named locks defined in lwlocknames.h each have their
- * own tranche.  The names of these tranches appear in IndividualLWLockNames[]
- * in lwlocknames.c.
+ * 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
@@ -126,9 +126,10 @@ StaticAssertDecl(LW_VAL_EXCLUSIVE > (uint32) MAX_BACKENDS,
  * All these names are user-visible as wait event names, so choose with care
  * ... and do not forget to update the documentation's list of wait events.
  */
-extern const char *const IndividualLWLockNames[];	/* in lwlocknames.c */
-
 static const char *const BuiltinTrancheNames[] = {
+#define PG_LWLOCK(id, lockname) [id] = CppAsString(lockname) "Lock",
+#include "storage/lwlocklist.h"
+#undef PG_LWLOCK
 	[LWTRANCHE_XACT_BUFFER] = "XactBuffer",
 	[LWTRANCHE_COMMITTS_BUFFER] = "CommitTsBuffer",
 	[LWTRANCHE_SUBTRANS_BUFFER] = "SubtransBuffer",
@@ -742,11 +743,7 @@ LWLockReportWaitEnd(void)
 static const char *
 GetLWTrancheName(uint16 trancheId)
 {
-	/* Individual LWLock? */
-	if (trancheId < NUM_INDIVIDUAL_LWLOCKS)
-		return IndividualLWLockNames[trancheId];
-
-	/* Built-in tranche? */
+	/* Built-in tranche or individual LWLock? */
 	if (trancheId < LWTRANCHE_FIRST_USER_DEFINED)
 		return BuiltinTrancheNames[trancheId];
 
diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt
deleted file mode 100644
index 284d168f77..0000000000
--- a/src/backend/storage/lmgr/lwlocknames.txt
+++ /dev/null
@@ -1,60 +0,0 @@
-# Some commonly-used locks have predefined positions within MainLWLockArray;
-# these are defined here.  If you add a lock, add it to the end to avoid
-# renumbering the existing locks; if you remove a lock, consider leaving a gap
-# in the numbering sequence for the benefit of DTrace and other external
-# debugging scripts.  Also, do not forget to update the section
-# WaitEventLWLock of src/backend/utils/activity/wait_event_names.txt.
-
-# 0 is available; was formerly BufFreelistLock
-ShmemIndexLock						1
-OidGenLock							2
-XidGenLock							3
-ProcArrayLock						4
-SInvalReadLock						5
-SInvalWriteLock						6
-WALBufMappingLock					7
-WALWriteLock						8
-ControlFileLock						9
-# 10 was CheckpointLock
-# 11 was XactSLRULock
-# 12 was SubtransSLRULock
-MultiXactGenLock					13
-# 14 was MultiXactOffsetSLRULock
-# 15 was MultiXactMemberSLRULock
-RelCacheInitLock					16
-CheckpointerCommLock				17
-TwoPhaseStateLock					18
-TablespaceCreateLock				19
-BtreeVacuumLock						20
-AddinShmemInitLock					21
-AutovacuumLock						22
-AutovacuumScheduleLock				23
-SyncScanLock						24
-RelationMappingLock					25
-#26 was NotifySLRULock
-NotifyQueueLock						27
-SerializableXactHashLock			28
-SerializableFinishedListLock		29
-SerializablePredicateListLock		30
-# 31 was SerialSLRULock
-SyncRepLock							32
-BackgroundWorkerLock				33
-DynamicSharedMemoryControlLock		34
-AutoFileLock						35
-ReplicationSlotAllocationLock		36
-ReplicationSlotControlLock			37
-#38 was CommitTsSLRULock
-CommitTsLock						39
-ReplicationOriginLock				40
-MultiXactTruncationLock				41
-# 42 was OldSnapshotTimeMapLock
-LogicalRepWorkerLock				43
-XactTruncationLock					44
-# 45 was XactTruncationLock until removal of BackendRandomLock
-WrapLimitsVacuumLock				46
-NotifyQueueTailLock					47
-WaitEventExtensionLock				48
-WALSummarizerLock					49
-DSMRegistryLock						50
-InjectionPointLock				51
-SerialControlLock					52
diff --git a/src/backend/storage/lmgr/meson.build b/src/backend/storage/lmgr/meson.build
index da32198f78..05ac41e809 100644
--- a/src/backend/storage/lmgr/meson.build
+++ b/src/backend/storage/lmgr/meson.build
@@ -11,5 +11,3 @@ backend_sources += files(
   's_lock.c',
   'spin.c',
 )
-
-generated_backend_sources += lwlocknames[1]
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index c08e00d1d6..b0ab833602 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -280,9 +280,9 @@ Extension	"Waiting in an extension."
 # This class of wait events has its own set of C structure, so these are
 # only used for the documentation.
 #
-# NB: Predefined LWLocks (i.e., those declared in lwlocknames.txt) must be
+# NB: Predefined LWLocks (i.e., those declared in lwlocknames.h) must be
 # listed in the top section of locks and must be listed in the same order as in
-# lwlocknames.txt.
+# lwlocknames.h.
 #
 
 Section: ClassName - WaitEventLWLock
@@ -333,9 +333,9 @@ SerialControl	"Waiting to read or update shared <filename>pg_serial</filename> s
 #
 # END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
 #
-# Predefined LWLocks (i.e., those declared in lwlocknames.txt) must be listed
+# 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.txt.  Other LWLocks must be listed in the section below.
+# lwlocknames.h.  Other LWLocks must be listed in the section below.
 #
 
 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 10bea8c595..3479b4cf52 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -19,6 +19,7 @@
 #endif
 
 #include "port/atomics.h"
+#include "storage/lwlocknames.h"
 #include "storage/proclist_types.h"
 
 struct PGPROC;
@@ -82,9 +83,6 @@ typedef struct NamedLWLockTranche
 extern PGDLLIMPORT NamedLWLockTranche *NamedLWLockTrancheArray;
 extern PGDLLIMPORT int NamedLWLockTrancheRequests;
 
-/* Names for fixed lwlocks */
-#include "storage/lwlocknames.h"
-
 /*
  * It's a bit odd to declare NUM_BUFFER_PARTITIONS and NUM_LOCK_PARTITIONS
  * here, but we need them to figure out offsets within MainLWLockArray, and
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
new file mode 100644
index 0000000000..85f6568b9e
--- /dev/null
+++ b/src/include/storage/lwlocklist.h
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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
+ * defined by the caller for special purposes.
+ *
+ * Also, generate-lwlocknames.pl processes this file to create lwlocknames.h.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *    src/include/storage/lwlocklist.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * Some commonly-used locks have predefined positions within MainLWLockArray;
+ * these are defined here.  If you add a lock, add it to the end to avoid
+ * renumbering the existing locks; if you remove a lock, consider leaving a gap
+ * in the numbering sequence for the benefit of DTrace and other external
+ * debugging scripts.  Also, do not forget to update the section
+ * WaitEventLWLock of src/backend/utils/activity/wait_event_names.txt.
+ *
+ * Note that the names here don't include the Lock suffix, to appease the
+ * C preprocessor; it's added elsewhere.
+ */
+
+/* 0 is available; was formerly BufFreelistLock */
+PG_LWLOCK(1, ShmemIndex)
+PG_LWLOCK(2, OidGen)
+PG_LWLOCK(3, XidGen)
+PG_LWLOCK(4, ProcArray)
+PG_LWLOCK(5, SInvalRead)
+PG_LWLOCK(6, SInvalWrite)
+PG_LWLOCK(7, WALBufMapping)
+PG_LWLOCK(8, WALWrite)
+PG_LWLOCK(9, ControlFile)
+/* 10 was CheckpointLock */
+/* 11 was XactSLRULock */
+/* 12 was SubtransSLRULock */
+PG_LWLOCK(13, MultiXactGen)
+/* 14 was MultiXactOffsetSLRULock */
+/* 15 was MultiXactMemberSLRULock */
+PG_LWLOCK(16, RelCacheInit)
+PG_LWLOCK(17, CheckpointerComm)
+PG_LWLOCK(18, TwoPhaseState)
+PG_LWLOCK(19, TablespaceCreate)
+PG_LWLOCK(20, BtreeVacuum)
+PG_LWLOCK(21, AddinShmemInit)
+PG_LWLOCK(22, Autovacuum)
+PG_LWLOCK(23, AutovacuumSchedule)
+PG_LWLOCK(24, SyncScan)
+PG_LWLOCK(25, RelationMapping)
+/* 26 was NotifySLRULock */
+PG_LWLOCK(27, NotifyQueue)
+PG_LWLOCK(28, SerializableXactHash)
+PG_LWLOCK(29, SerializableFinishedList)
+PG_LWLOCK(30, SerializablePredicateList)
+/* 31 was SerialSLRULock */
+PG_LWLOCK(32, SyncRep)
+PG_LWLOCK(33, BackgroundWorker)
+PG_LWLOCK(34, DynamicSharedMemoryControl)
+PG_LWLOCK(35, AutoFile)
+PG_LWLOCK(36, ReplicationSlotAllocation)
+PG_LWLOCK(37, ReplicationSlotControl)
+/* 38 was CommitTsSLRULock */
+PG_LWLOCK(39, CommitTs)
+PG_LWLOCK(40, ReplicationOrigin)
+PG_LWLOCK(41, MultiXactTruncation)
+/* 42 was OldSnapshotTimeMapLock */
+PG_LWLOCK(43, LogicalRepWorker)
+PG_LWLOCK(44, XactTruncation)
+/* 45 was XactTruncationLock until removal of BackendRandomLock */
+PG_LWLOCK(46, WrapLimitsVacuum)
+PG_LWLOCK(47, NotifyQueueTail)
+PG_LWLOCK(48, WaitEventExtension)
+PG_LWLOCK(49, WALSummarizer)
+PG_LWLOCK(50, DSMRegistry)
+PG_LWLOCK(51, InjectionPoint)
+PG_LWLOCK(52, SerialControl)
diff --git a/src/include/storage/meson.build b/src/include/storage/meson.build
index 666fb22408..f889093117 100644
--- a/src/include/storage/meson.build
+++ b/src/include/storage/meson.build
@@ -1,10 +1,10 @@
 # Copyright (c) 2022-2024, PostgreSQL Global Development Group
 
-lwlocknames = custom_target('lwlocknames',
+lwlocknames_h = custom_target('lwlocknames_h',
   input: files(
-    '../../backend/storage/lmgr/lwlocknames.txt',
+    '../../include/storage/lwlocklist.h',
     '../../backend/utils/activity/wait_event_names.txt'),
-  output: ['lwlocknames.h', 'lwlocknames.c'],
+  output: ['lwlocknames.h'],
   command: [
     perl, files('../../backend/storage/lmgr/generate-lwlocknames.pl'),
     '-o', '@OUTDIR@',
@@ -12,12 +12,10 @@ lwlocknames = custom_target('lwlocknames',
   ],
   build_by_default: true,
   install: true,
-  install_dir: [dir_include_server / 'storage', false],
+  install_dir: dir_include_server / 'storage',
 )
 
-lwlocknames_h = lwlocknames[0]
-
 generated_backend_headers += lwlocknames_h
 
 # autoconf generates the file there, ensure we get a conflict
-generated_sources_ac += {'src/backend/storage/lmgr': ['lwlocknames.c', 'lwlocknames.h']}
+generated_sources_ac += {'src/backend/storage/lmgr': ['lwlocknames.h']}
diff --git a/src/tools/pginclude/headerscheck b/src/tools/pginclude/headerscheck
index 5c12ab99b8..13b9735f84 100755
--- a/src/tools/pginclude/headerscheck
+++ b/src/tools/pginclude/headerscheck
@@ -133,6 +133,7 @@ do
 	test "$f" = src/interfaces/ecpg/preproc/c_kwlist.h && continue
 	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/tcop/cmdtaglist.h && continue
 	test "$f" = src/pl/plpgsql/src/plerrcodes.h && continue
 	test "$f" = src/pl/plpython/spiexceptions.h && continue
-- 
2.39.2

