From d646b6ba4ec743b5294a51875813d614276fd805 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Mon, 3 Jul 2023 15:51:40 +0900
Subject: [PATCH v11] Generate automatically wait-event related code and docs

Purpose is to auto-generate those files based on the newly created
waiteventnames.txt file.

Having auto generated files would help to avoid:

- wait event without description like observed in
- https://www.postgresql.org/message-id/CA%2BhUKGJixAHc860Ej9Qzd_z96Z6aoajAgJ18bYfV3Lfn6t9%3D%2BQ%40mail.gmail.com
- orphaned wait event like observed in
- https://www.postgresql.org/message-id/CA%2BhUKGK6tqm59KuF1z%2Bh5Y8fsWcu5v8%2B84kduSHwRzwjB2aa_A%40mail.gmail.com
---
 src/include/Makefile                          |    2 +-
 src/include/utils/.gitignore                  |    1 +
 src/include/utils/meson.build                 |   18 +
 src/include/utils/wait_event.h                |  232 +--
 src/backend/Makefile                          |   13 +-
 src/backend/storage/lmgr/lwlocknames.txt      |    4 +-
 src/backend/utils/activity/.gitignore         |    3 +
 src/backend/utils/activity/Makefile           |   10 +
 .../activity/generate-wait_event_types.pl     |  219 +++
 src/backend/utils/activity/meson.build        |   24 +
 src/backend/utils/activity/wait_event.c       |  611 +-------
 .../utils/activity/wait_event_names.txt       |  371 +++++
 src/backend/utils/adt/lockfuncs.c             |    3 +-
 src/common/meson.build                        |    7 +-
 src/test/ssl/t/002_scram.pl                   |    3 +-
 doc/src/sgml/.gitignore                       |    1 +
 doc/src/sgml/Makefile                         |    5 +-
 doc/src/sgml/filelist.sgml                    |    1 +
 doc/src/sgml/meson.build                      |   12 +
 doc/src/sgml/monitoring.sgml                  | 1271 +----------------
 src/tools/msvc/Solution.pm                    |   19 +
 src/tools/msvc/clean.bat                      |    3 +
 22 files changed, 722 insertions(+), 2111 deletions(-)
 create mode 100644 src/backend/utils/activity/.gitignore
 create mode 100644 src/backend/utils/activity/generate-wait_event_types.pl
 create mode 100644 src/backend/utils/activity/wait_event_names.txt

diff --git a/src/include/Makefile b/src/include/Makefile
index 56576dcf5c..5d213187e2 100644
--- a/src/include/Makefile
+++ b/src/include/Makefile
@@ -72,7 +72,7 @@ uninstall:
 
 clean:
 	rm -f utils/fmgroids.h utils/fmgrprotos.h utils/errcodes.h utils/header-stamp
-	rm -f storage/lwlocknames.h utils/probes.h
+	rm -f storage/lwlocknames.h utils/probes.h utils/wait_event_types.h
 	rm -f catalog/schemapg.h catalog/system_fk_info.h
 	rm -f catalog/pg_*_d.h catalog/header-stamp
 	rm -f nodes/nodetags.h nodes/header-stamp
diff --git a/src/include/utils/.gitignore b/src/include/utils/.gitignore
index 05cfa7a8d6..c1b4c66213 100644
--- a/src/include/utils/.gitignore
+++ b/src/include/utils/.gitignore
@@ -3,3 +3,4 @@
 /probes.h
 /errcodes.h
 /header-stamp
+/wait_event_types.h
diff --git a/src/include/utils/meson.build b/src/include/utils/meson.build
index c212c4091f..bbbc54fa07 100644
--- a/src/include/utils/meson.build
+++ b/src/include/utils/meson.build
@@ -1,5 +1,21 @@
 # Copyright (c) 2022-2023, PostgreSQL Global Development Group
 
+wait_event_names = custom_target('wait_event_names',
+  input: files('../../backend/utils/activity/wait_event_names.txt'),
+  output: ['wait_event_types.h'],
+  command: [
+    perl, files('../../backend/utils/activity/generate-wait_event_types.pl'),
+    '-o', '@OUTDIR@',
+    '@INPUT@'
+  ],
+  build_by_default: true,
+  install: true,
+  install_dir: [dir_include_server / 'utils'],
+)
+
+wait_event_types_h = wait_event_names[0]
+generated_backend_headers += wait_event_types_h
+
 errcodes = custom_target('errcodes',
   input: files('../../backend/utils/errcodes.txt'),
   output: ['errcodes.h'],
@@ -58,3 +74,5 @@ generated_sources_ac += {
   'src/backend/utils': fmgrtab_output + ['errcodes.h', 'probes.h', 'fmgr-stamp'],
   'src/include/utils': ['header-stamp'],
 }
+
+generated_sources_ac += {'src/backend/utils/activity': ['wait_event_types.h']}
diff --git a/src/include/utils/wait_event.h b/src/include/utils/wait_event.h
index dc01d4e84d..4517425f84 100644
--- a/src/include/utils/wait_event.h
+++ b/src/include/utils/wait_event.h
@@ -25,236 +25,8 @@
 #define PG_WAIT_TIMEOUT				0x09000000U
 #define PG_WAIT_IO					0x0A000000U
 
-/* ----------
- * Wait Events - Activity
- *
- * Use this category when a process is waiting because it has no work to do,
- * unless the "Client" or "Timeout" category describes the situation better.
- * Typically, this should only be used for background processes.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_ARCHIVER_MAIN = PG_WAIT_ACTIVITY,
-	WAIT_EVENT_AUTOVACUUM_MAIN,
-	WAIT_EVENT_BGWRITER_HIBERNATE,
-	WAIT_EVENT_BGWRITER_MAIN,
-	WAIT_EVENT_CHECKPOINTER_MAIN,
-	WAIT_EVENT_LOGICAL_APPLY_MAIN,
-	WAIT_EVENT_LOGICAL_LAUNCHER_MAIN,
-	WAIT_EVENT_LOGICAL_PARALLEL_APPLY_MAIN,
-	WAIT_EVENT_RECOVERY_WAL_STREAM,
-	WAIT_EVENT_SYSLOGGER_MAIN,
-	WAIT_EVENT_WAL_RECEIVER_MAIN,
-	WAIT_EVENT_WAL_SENDER_MAIN,
-	WAIT_EVENT_WAL_WRITER_MAIN
-} WaitEventActivity;
-
-/* ----------
- * Wait Events - BUFFERPIN
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_BUFFER_PIN = PG_WAIT_BUFFERPIN
-} WaitEventBufferPin;
-
-/* ----------
- * Wait Events - Client
- *
- * Use this category when a process is waiting to send data to or receive data
- * from the frontend process to which it is connected.  This is never used for
- * a background process, which has no client connection.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_CLIENT_READ = PG_WAIT_CLIENT,
-	WAIT_EVENT_CLIENT_WRITE,
-	WAIT_EVENT_GSS_OPEN_SERVER,
-	WAIT_EVENT_LIBPQWALRECEIVER_CONNECT,
-	WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE,
-	WAIT_EVENT_SSL_OPEN_SERVER,
-	WAIT_EVENT_WAL_SENDER_WAIT_WAL,
-	WAIT_EVENT_WAL_SENDER_WRITE_DATA,
-} WaitEventClient;
-
-/* ----------
- * Wait Events - EXTENSION
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_EXTENSION = PG_WAIT_EXTENSION
-} WaitEventExtension;
-
-/* ----------
- * Wait Events - IPC
- *
- * Use this category when a process cannot complete the work it is doing because
- * it is waiting for a notification from another process.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_APPEND_READY = PG_WAIT_IPC,
-	WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND,
-	WAIT_EVENT_ARCHIVE_COMMAND,
-	WAIT_EVENT_BACKEND_TERMINATION,
-	WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE,
-	WAIT_EVENT_BGWORKER_SHUTDOWN,
-	WAIT_EVENT_BGWORKER_STARTUP,
-	WAIT_EVENT_BTREE_PAGE,
-	WAIT_EVENT_BUFFER_IO,
-	WAIT_EVENT_CHECKPOINT_DONE,
-	WAIT_EVENT_CHECKPOINT_START,
-	WAIT_EVENT_EXECUTE_GATHER,
-	WAIT_EVENT_HASH_BATCH_ALLOCATE,
-	WAIT_EVENT_HASH_BATCH_ELECT,
-	WAIT_EVENT_HASH_BATCH_LOAD,
-	WAIT_EVENT_HASH_BUILD_ALLOCATE,
-	WAIT_EVENT_HASH_BUILD_ELECT,
-	WAIT_EVENT_HASH_BUILD_HASH_INNER,
-	WAIT_EVENT_HASH_BUILD_HASH_OUTER,
-	WAIT_EVENT_HASH_GROW_BATCHES_DECIDE,
-	WAIT_EVENT_HASH_GROW_BATCHES_ELECT,
-	WAIT_EVENT_HASH_GROW_BATCHES_FINISH,
-	WAIT_EVENT_HASH_GROW_BATCHES_REALLOCATE,
-	WAIT_EVENT_HASH_GROW_BATCHES_REPARTITION,
-	WAIT_EVENT_HASH_GROW_BUCKETS_ELECT,
-	WAIT_EVENT_HASH_GROW_BUCKETS_REALLOCATE,
-	WAIT_EVENT_HASH_GROW_BUCKETS_REINSERT,
-	WAIT_EVENT_LOGICAL_APPLY_SEND_DATA,
-	WAIT_EVENT_LOGICAL_PARALLEL_APPLY_STATE_CHANGE,
-	WAIT_EVENT_LOGICAL_SYNC_DATA,
-	WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE,
-	WAIT_EVENT_MQ_INTERNAL,
-	WAIT_EVENT_MQ_PUT_MESSAGE,
-	WAIT_EVENT_MQ_RECEIVE,
-	WAIT_EVENT_MQ_SEND,
-	WAIT_EVENT_PARALLEL_BITMAP_SCAN,
-	WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN,
-	WAIT_EVENT_PARALLEL_FINISH,
-	WAIT_EVENT_PROCARRAY_GROUP_UPDATE,
-	WAIT_EVENT_PROC_SIGNAL_BARRIER,
-	WAIT_EVENT_PROMOTE,
-	WAIT_EVENT_RECOVERY_CONFLICT_SNAPSHOT,
-	WAIT_EVENT_RECOVERY_CONFLICT_TABLESPACE,
-	WAIT_EVENT_RECOVERY_END_COMMAND,
-	WAIT_EVENT_RECOVERY_PAUSE,
-	WAIT_EVENT_REPLICATION_ORIGIN_DROP,
-	WAIT_EVENT_REPLICATION_SLOT_DROP,
-	WAIT_EVENT_RESTORE_COMMAND,
-	WAIT_EVENT_SAFE_SNAPSHOT,
-	WAIT_EVENT_SYNC_REP,
-	WAIT_EVENT_WAL_RECEIVER_EXIT,
-	WAIT_EVENT_WAL_RECEIVER_WAIT_START,
-	WAIT_EVENT_XACT_GROUP_UPDATE
-} WaitEventIPC;
-
-/* ----------
- * Wait Events - Timeout
- *
- * Use this category when a process is waiting for a timeout to expire.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_BASE_BACKUP_THROTTLE = PG_WAIT_TIMEOUT,
-	WAIT_EVENT_CHECKPOINT_WRITE_DELAY,
-	WAIT_EVENT_PG_SLEEP,
-	WAIT_EVENT_RECOVERY_APPLY_DELAY,
-	WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL,
-	WAIT_EVENT_REGISTER_SYNC_REQUEST,
-	WAIT_EVENT_SPIN_DELAY,
-	WAIT_EVENT_VACUUM_DELAY,
-	WAIT_EVENT_VACUUM_TRUNCATE
-} WaitEventTimeout;
-
-/* ----------
- * Wait Events - IO
- *
- * Use this category when a process is waiting for a IO.
- * ----------
- */
-typedef enum
-{
-	WAIT_EVENT_BASEBACKUP_READ = PG_WAIT_IO,
-	WAIT_EVENT_BASEBACKUP_SYNC,
-	WAIT_EVENT_BASEBACKUP_WRITE,
-	WAIT_EVENT_BUFFILE_READ,
-	WAIT_EVENT_BUFFILE_WRITE,
-	WAIT_EVENT_BUFFILE_TRUNCATE,
-	WAIT_EVENT_CONTROL_FILE_READ,
-	WAIT_EVENT_CONTROL_FILE_SYNC,
-	WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE,
-	WAIT_EVENT_CONTROL_FILE_WRITE,
-	WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE,
-	WAIT_EVENT_COPY_FILE_READ,
-	WAIT_EVENT_COPY_FILE_WRITE,
-	WAIT_EVENT_DATA_FILE_EXTEND,
-	WAIT_EVENT_DATA_FILE_FLUSH,
-	WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC,
-	WAIT_EVENT_DATA_FILE_PREFETCH,
-	WAIT_EVENT_DATA_FILE_READ,
-	WAIT_EVENT_DATA_FILE_SYNC,
-	WAIT_EVENT_DATA_FILE_TRUNCATE,
-	WAIT_EVENT_DATA_FILE_WRITE,
-	WAIT_EVENT_DSM_ALLOCATE,
-	WAIT_EVENT_DSM_FILL_ZERO_WRITE,
-	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ,
-	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC,
-	WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE,
-	WAIT_EVENT_LOCK_FILE_CREATE_READ,
-	WAIT_EVENT_LOCK_FILE_CREATE_SYNC,
-	WAIT_EVENT_LOCK_FILE_CREATE_WRITE,
-	WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ,
-	WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC,
-	WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC,
-	WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE,
-	WAIT_EVENT_LOGICAL_REWRITE_SYNC,
-	WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE,
-	WAIT_EVENT_LOGICAL_REWRITE_WRITE,
-	WAIT_EVENT_RELATION_MAP_READ,
-	WAIT_EVENT_RELATION_MAP_REPLACE,
-	WAIT_EVENT_RELATION_MAP_WRITE,
-	WAIT_EVENT_REORDER_BUFFER_READ,
-	WAIT_EVENT_REORDER_BUFFER_WRITE,
-	WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ,
-	WAIT_EVENT_REPLICATION_SLOT_READ,
-	WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC,
-	WAIT_EVENT_REPLICATION_SLOT_SYNC,
-	WAIT_EVENT_REPLICATION_SLOT_WRITE,
-	WAIT_EVENT_SLRU_FLUSH_SYNC,
-	WAIT_EVENT_SLRU_READ,
-	WAIT_EVENT_SLRU_SYNC,
-	WAIT_EVENT_SLRU_WRITE,
-	WAIT_EVENT_SNAPBUILD_READ,
-	WAIT_EVENT_SNAPBUILD_SYNC,
-	WAIT_EVENT_SNAPBUILD_WRITE,
-	WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC,
-	WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE,
-	WAIT_EVENT_TIMELINE_HISTORY_READ,
-	WAIT_EVENT_TIMELINE_HISTORY_SYNC,
-	WAIT_EVENT_TIMELINE_HISTORY_WRITE,
-	WAIT_EVENT_TWOPHASE_FILE_READ,
-	WAIT_EVENT_TWOPHASE_FILE_SYNC,
-	WAIT_EVENT_TWOPHASE_FILE_WRITE,
-	WAIT_EVENT_VERSION_FILE_WRITE,
-	WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ,
-	WAIT_EVENT_WAL_BOOTSTRAP_SYNC,
-	WAIT_EVENT_WAL_BOOTSTRAP_WRITE,
-	WAIT_EVENT_WAL_COPY_READ,
-	WAIT_EVENT_WAL_COPY_SYNC,
-	WAIT_EVENT_WAL_COPY_WRITE,
-	WAIT_EVENT_WAL_INIT_SYNC,
-	WAIT_EVENT_WAL_INIT_WRITE,
-	WAIT_EVENT_WAL_READ,
-	WAIT_EVENT_WAL_SYNC,
-	WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN,
-	WAIT_EVENT_WAL_WRITE
-} WaitEventIO;
-
+/* enums for wait events */
+#include "utils/wait_event_types.h"
 
 extern const char *pgstat_get_wait_event(uint32 wait_event_info);
 extern const char *pgstat_get_wait_event_type(uint32 wait_event_info);
diff --git a/src/backend/Makefile b/src/backend/Makefile
index 3c42003175..1c929383c4 100644
--- a/src/backend/Makefile
+++ b/src/backend/Makefile
@@ -133,6 +133,9 @@ parser/gram.h: parser/gram.y
 storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
 	$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
 
+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
+
 # run this unconditionally to avoid needing to know its dependencies here:
 submake-catalog-headers:
 	$(MAKE) -C catalog distprep generated-header-symlinks
@@ -160,13 +163,18 @@ submake-utils-headers:
 
 .PHONY: generated-headers
 
-generated-headers: $(top_builddir)/src/include/storage/lwlocknames.h submake-catalog-headers submake-nodes-headers submake-utils-headers
+generated-headers: $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/wait_event_types.h submake-catalog-headers submake-nodes-headers submake-utils-headers
 
 $(top_builddir)/src/include/storage/lwlocknames.h: storage/lmgr/lwlocknames.h
 	prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
 	  cd '$(dir $@)' && rm -f $(notdir $@) && \
 	  $(LN_S) "$$prereqdir/$(notdir $<)" .
 
+$(top_builddir)/src/include/utils/wait_event_types.h: utils/activity/wait_event_types.h
+	prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
+	  cd '$(dir $@)' && rm -f $(notdir $@) && \
+	  $(LN_S) "$$prereqdir/$(notdir $<)" .
+
 utils/probes.o: utils/probes.d $(SUBDIROBJS)
 	$(DTRACE) $(DTRACEFLAGS) -C -G -s $(call expand_subsys,$^) -o $@
 
@@ -182,6 +190,7 @@ distprep:
 	$(MAKE) -C replication	repl_gram.c repl_gram.h repl_scanner.c syncrep_gram.c syncrep_gram.h syncrep_scanner.c
 	$(MAKE) -C storage/lmgr	lwlocknames.h lwlocknames.c
 	$(MAKE) -C utils	distprep
+	$(MAKE) -C utils/activity	wait_event_types.h pgstat_wait_event.c
 	$(MAKE) -C utils/adt	jsonpath_gram.c jsonpath_gram.h jsonpath_scan.c
 	$(MAKE) -C utils/misc	guc-file.c
 
@@ -301,6 +310,8 @@ maintainer-clean: distclean
 	      replication/syncrep_scanner.c \
 	      storage/lmgr/lwlocknames.c \
 	      storage/lmgr/lwlocknames.h \
+	      utils/activity/pgstat_wait_event.c \
+	      utils/activity/wait_event_types.h \
 	      utils/adt/jsonpath_gram.c \
 	      utils/adt/jsonpath_gram.h \
 	      utils/adt/jsonpath_scan.c \
diff --git a/src/backend/storage/lmgr/lwlocknames.txt b/src/backend/storage/lmgr/lwlocknames.txt
index 6c7cf6c295..b34b6afecd 100644
--- a/src/backend/storage/lmgr/lwlocknames.txt
+++ b/src/backend/storage/lmgr/lwlocknames.txt
@@ -2,8 +2,8 @@
 # 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 list of wait events
-# in the user documentation.
+# 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
diff --git a/src/backend/utils/activity/.gitignore b/src/backend/utils/activity/.gitignore
new file mode 100644
index 0000000000..a62378405e
--- /dev/null
+++ b/src/backend/utils/activity/.gitignore
@@ -0,0 +1,3 @@
+/pgstat_wait_event.c
+/wait_event_types.h
+/wait_event_types.sgml
diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile
index 7d7482dde0..5ec53edce9 100644
--- a/src/backend/utils/activity/Makefile
+++ b/src/backend/utils/activity/Makefile
@@ -33,3 +33,13 @@ OBJS = \
 	wait_event.o
 
 include $(top_srcdir)/src/backend/common.mk
+
+wait_event.o: pgstat_wait_event.c
+pgstat_wait_event.c: wait_event_types.h
+	touch $@
+
+wait_event_types.h: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt generate-wait_event_types.pl
+	$(PERL) $(srcdir)/generate-wait_event_types.pl $<
+
+maintainer-clean: clean
+	rm -f wait_event_types.h pgstat_wait_event.c
diff --git a/src/backend/utils/activity/generate-wait_event_types.pl b/src/backend/utils/activity/generate-wait_event_types.pl
new file mode 100644
index 0000000000..3991a724bb
--- /dev/null
+++ b/src/backend/utils/activity/generate-wait_event_types.pl
@@ -0,0 +1,219 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# Generate wait events support files from wait_event_names.txt:
+# - wait_event_types.h
+# - pgstat_wait_event.c
+# - wait_event_types.sgml
+#
+# Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/backend/utils/activity/generate-wait_event_types.pl
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+my $output_path = '.';
+
+my $continue = "\n";
+my %hashwe;
+
+GetOptions('outdir:s' => \$output_path);
+
+open my $wait_event_names, '<', $ARGV[0] or die;
+
+# Include PID in suffix in case parallel make runs this multiple times.
+my $htmp = "$output_path/wait_event_types.h.tmp$$";
+my $ctmp = "$output_path/pgstat_wait_event.c.tmp$$";
+my $stmp = "$output_path/wait_event_names.s.tmp$$";
+open my $h, '>', $htmp or die "Could not open $htmp: $!";
+open my $c, '>', $ctmp or die "Could not open $ctmp: $!";
+open my $s, '>', $stmp or die "Could not open $stmp: $!";
+
+my $header_comment =
+  '/*-------------------------------------------------------------------------
+ *
+ * %s
+ *    Generated wait events infrastructure code
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ *  ******************************
+ *  *** DO NOT EDIT THIS FILE! ***
+ *  ******************************
+ *
+ *  It has been GENERATED by src/backend/utils/activity/generate-wait_event_types.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+';
+
+printf $h $header_comment, 'wait_event_types.h';
+printf $h "#ifndef WAIT_EVENT_TYPES_H\n";
+printf $h "#define WAIT_EVENT_TYPES_H\n\n";
+printf $h "#include \"utils/wait_event.h\"\n\n";
+
+printf $c $header_comment, 'pgstat_wait_event.c';
+
+my @lines;
+my $section_name;
+my $note;
+my $note_name;
+
+# Remove comments and empty lines and add waitclassname based on the section
+while (<$wait_event_names>)
+{
+	chomp;
+
+	# Skip comments
+	next if /^#/;
+
+	# Skip empty lines
+	next if /^\s*$/;
+
+	# Get waitclassname based on the section
+	if (/^Section: ClassName(.*)/)
+	{
+		$section_name = $_;
+		$section_name =~ s/^.*- //;
+		next;
+	}
+
+	push(@lines, $section_name . "\t" . $_);
+}
+
+# Sort the lines based on the third column.
+# uc() is being used to force the comparison to be case-insensitive.
+my @lines_sorted =
+  sort { uc((split(/\t/, $a))[2]) cmp uc((split(/\t/, $b))[2]) } @lines;
+
+# Read the sorted lines and populate the hash table
+foreach my $line (@lines_sorted)
+{
+	die "unable to parse wait_event_names.txt"
+	  unless $line =~ /^(\w+)\t+(\w+)\t+("\w+")\t+("\w.*\.")$/;
+
+	(   my $waitclassname,
+		my $waiteventenumname,
+		my $waiteventdescription,
+		my $waitevendocsentence) = split(/\t/, $line);
+
+	my @waiteventlist =
+	  [ $waiteventenumname, $waiteventdescription, $waitevendocsentence ];
+	my $trimmedwaiteventname = $waiteventenumname;
+	$trimmedwaiteventname =~ s/^WAIT_EVENT_//;
+
+	# An exception is required for LWLock and Lock as these don't require
+	# any C and header files generated.
+	die "wait event names must start with 'WAIT_EVENT_'"
+	  if ( $trimmedwaiteventname eq $waiteventenumname
+		&& $waiteventenumname !~ /^LWLock/
+		&& $waiteventenumname !~ /^Lock/);
+	$continue = ",\n";
+	push(@{ $hashwe{$waitclassname} }, @waiteventlist);
+}
+
+# Generate the .c and .h files.
+# uc() is being used to force the comparison to be case-insensitive.
+foreach my $waitclass (sort { uc($a) cmp uc($b) } keys %hashwe)
+{
+
+	# Don't generate .c and .h files for LWLock and Lock, these are
+	# handled independently.
+	next
+	  if ( $waitclass =~ /^WaitEventLWLock$/
+		|| $waitclass =~ /^WaitEventLock$/);
+
+	my $last = $waitclass;
+	$last =~ s/^WaitEvent//;
+	my $lastuc = uc $last;
+	my $lastlc = lc $last;
+	my $firstpass = 1;
+	my $pg_wait_class;
+
+	printf $c
+	  "static const char *\npgstat_get_wait_$lastlc($waitclass w)\n{\n";
+	printf $c "\tconst char *event_name = \"unknown wait event\";\n\n";
+	printf $c "\tswitch (w)\n\t{\n";
+
+	foreach my $wev (@{ $hashwe{$waitclass} })
+	{
+		if ($firstpass)
+		{
+			printf $h "typedef enum\n{\n";
+			$pg_wait_class = "PG_WAIT_" . $lastuc;
+			printf $h "\t%s = %s", $wev->[0], $pg_wait_class;
+			$continue = ",\n";
+		}
+		else
+		{
+			printf $h "%s\t%s", $continue, $wev->[0];
+			$continue = ",\n";
+		}
+		$firstpass = 0;
+
+		printf $c "\t\t case %s:\n", $wev->[0];
+		printf $c "\t\t\t event_name = %s;\n\t\t\t break;\n", $wev->[1];
+	}
+
+	printf $h "\n} $waitclass;\n\n";
+
+	printf $c "\t\t\t /* no default case, so that compiler will warn */\n";
+	printf $c "\t}\n\n";
+	printf $c "\treturn event_name;\n";
+	printf $c "}\n\n";
+}
+
+printf $h "#endif                          /* WAIT_EVENT_TYPES_H */";
+close $h;
+close $c;
+
+# Generate the .sgml file.
+# uc() is being used to force the comparison to be case-insensitive.
+foreach my $waitclass (sort { uc($a) cmp uc($b) } keys %hashwe)
+{
+	my $last = $waitclass;
+	$last =~ s/^WaitEvent//;
+	my $lastlc = lc $last;
+
+	printf $s "  <table id=\"wait-event-%s-table\">\n", $lastlc;
+	printf $s "   <title>Wait Events of Type <literal>%s</literal></title>\n",
+	  ucfirst($lastlc);
+	printf $s "   <tgroup cols=\"2\">\n";
+	printf $s "    <thead>\n";
+	printf $s "     <row>\n";
+	printf $s "      <entry><literal>$last</literal> Wait Event</entry>\n";
+	printf $s "      <entry>Description</entry>\n";
+	printf $s "     </row>\n";
+	printf $s "    </thead>\n\n";
+	printf $s "    <tbody>\n";
+
+	foreach my $wev (@{ $hashwe{$waitclass} })
+	{
+		printf $s "     <row>\n";
+		printf $s "      <entry><literal>%s</literal></entry>\n",
+		  substr $wev->[1], 1, -1;
+		printf $s "      <entry>%s</entry>\n", substr $wev->[2], 1, -1;
+		printf $s "     </row>\n";
+	}
+
+	printf $s "    </tbody>\n";
+	printf $s "   </tgroup>\n";
+	printf $s "  </table>\n\n";
+}
+
+close $s;
+
+rename($htmp, "$output_path/wait_event_types.h")
+  || die "rename: $htmp to $output_path/wait_event_types.h: $!";
+rename($ctmp, "$output_path/pgstat_wait_event.c") || die "rename: $ctmp: $!";
+rename($stmp, "$output_path/wait_event_types.sgml")
+  || die "rename: $ctmp: $!";
+
+close $wait_event_names;
diff --git a/src/backend/utils/activity/meson.build b/src/backend/utils/activity/meson.build
index 518ee3f798..070c4be66e 100644
--- a/src/backend/utils/activity/meson.build
+++ b/src/backend/utils/activity/meson.build
@@ -1,5 +1,17 @@
 # Copyright (c) 2022-2023, PostgreSQL Global Development Group
 
+wait_event_names = custom_target('wait_event_names',
+  input: files('./wait_event_names.txt'),
+  output: ['pgstat_wait_event.c'],
+  command: [
+    perl, files('./generate-wait_event_types.pl'),
+    '-o', '@OUTDIR@',
+    '@INPUT@'
+  ],
+  install: true,
+  install_dir: [false],
+)
+
 backend_sources += files(
   'backend_progress.c',
   'backend_status.c',
@@ -17,5 +29,17 @@ backend_sources += files(
   'pgstat_subscription.c',
   'pgstat_wal.c',
   'pgstat_xact.c',
+)
+
+# these include .c files generated in ../../../include/activity, seems nicer to not
+# add that as an include path for the whole backend
+waitevent_sources = files(
   'wait_event.c',
 )
+
+backend_link_with += static_library('wait_event_names',
+  waitevent_sources,
+  dependencies: [backend_code],
+  include_directories: include_directories('../../../include/utils'),
+  kwargs: internal_lib_args,
+)
diff --git a/src/backend/utils/activity/wait_event.c b/src/backend/utils/activity/wait_event.c
index 8572cf169e..4aad11c111 100644
--- a/src/backend/utils/activity/wait_event.c
+++ b/src/backend/utils/activity/wait_event.c
@@ -206,613 +206,4 @@ pgstat_get_wait_event(uint32 wait_event_info)
 	return event_name;
 }
 
-/* ----------
- * pgstat_get_wait_activity() -
- *
- * Convert WaitEventActivity to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_activity(WaitEventActivity w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_ARCHIVER_MAIN:
-			event_name = "ArchiverMain";
-			break;
-		case WAIT_EVENT_AUTOVACUUM_MAIN:
-			event_name = "AutoVacuumMain";
-			break;
-		case WAIT_EVENT_BGWRITER_HIBERNATE:
-			event_name = "BgWriterHibernate";
-			break;
-		case WAIT_EVENT_BGWRITER_MAIN:
-			event_name = "BgWriterMain";
-			break;
-		case WAIT_EVENT_CHECKPOINTER_MAIN:
-			event_name = "CheckpointerMain";
-			break;
-		case WAIT_EVENT_LOGICAL_APPLY_MAIN:
-			event_name = "LogicalApplyMain";
-			break;
-		case WAIT_EVENT_LOGICAL_LAUNCHER_MAIN:
-			event_name = "LogicalLauncherMain";
-			break;
-		case WAIT_EVENT_LOGICAL_PARALLEL_APPLY_MAIN:
-			event_name = "LogicalParallelApplyMain";
-			break;
-		case WAIT_EVENT_RECOVERY_WAL_STREAM:
-			event_name = "RecoveryWalStream";
-			break;
-		case WAIT_EVENT_SYSLOGGER_MAIN:
-			event_name = "SysLoggerMain";
-			break;
-		case WAIT_EVENT_WAL_RECEIVER_MAIN:
-			event_name = "WalReceiverMain";
-			break;
-		case WAIT_EVENT_WAL_SENDER_MAIN:
-			event_name = "WalSenderMain";
-			break;
-		case WAIT_EVENT_WAL_WRITER_MAIN:
-			event_name = "WalWriterMain";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_bufferpin() -
- *
- * Convert WaitEventBufferPin to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_bufferpin(WaitEventBufferPin w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_BUFFER_PIN:
-			event_name = "BufferPin";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_client() -
- *
- * Convert WaitEventClient to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_client(WaitEventClient w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_CLIENT_READ:
-			event_name = "ClientRead";
-			break;
-		case WAIT_EVENT_CLIENT_WRITE:
-			event_name = "ClientWrite";
-			break;
-		case WAIT_EVENT_GSS_OPEN_SERVER:
-			event_name = "GSSOpenServer";
-			break;
-		case WAIT_EVENT_LIBPQWALRECEIVER_CONNECT:
-			event_name = "LibPQWalReceiverConnect";
-			break;
-		case WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE:
-			event_name = "LibPQWalReceiverReceive";
-			break;
-		case WAIT_EVENT_SSL_OPEN_SERVER:
-			event_name = "SSLOpenServer";
-			break;
-		case WAIT_EVENT_WAL_SENDER_WAIT_WAL:
-			event_name = "WalSenderWaitForWAL";
-			break;
-		case WAIT_EVENT_WAL_SENDER_WRITE_DATA:
-			event_name = "WalSenderWriteData";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_extension() -
- *
- * Convert WaitEventExtension to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_extension(WaitEventExtension w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_EXTENSION:
-			event_name = "Extension";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_ipc() -
- *
- * Convert WaitEventIPC to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_ipc(WaitEventIPC w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_APPEND_READY:
-			event_name = "AppendReady";
-			break;
-		case WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND:
-			event_name = "ArchiveCleanupCommand";
-			break;
-		case WAIT_EVENT_ARCHIVE_COMMAND:
-			event_name = "ArchiveCommand";
-			break;
-		case WAIT_EVENT_BACKEND_TERMINATION:
-			event_name = "BackendTermination";
-			break;
-		case WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE:
-			event_name = "BackupWaitWalArchive";
-			break;
-		case WAIT_EVENT_BGWORKER_SHUTDOWN:
-			event_name = "BgWorkerShutdown";
-			break;
-		case WAIT_EVENT_BGWORKER_STARTUP:
-			event_name = "BgWorkerStartup";
-			break;
-		case WAIT_EVENT_BTREE_PAGE:
-			event_name = "BtreePage";
-			break;
-		case WAIT_EVENT_BUFFER_IO:
-			event_name = "BufferIO";
-			break;
-		case WAIT_EVENT_CHECKPOINT_DONE:
-			event_name = "CheckpointDone";
-			break;
-		case WAIT_EVENT_CHECKPOINT_START:
-			event_name = "CheckpointStart";
-			break;
-		case WAIT_EVENT_EXECUTE_GATHER:
-			event_name = "ExecuteGather";
-			break;
-		case WAIT_EVENT_HASH_BATCH_ALLOCATE:
-			event_name = "HashBatchAllocate";
-			break;
-		case WAIT_EVENT_HASH_BATCH_ELECT:
-			event_name = "HashBatchElect";
-			break;
-		case WAIT_EVENT_HASH_BATCH_LOAD:
-			event_name = "HashBatchLoad";
-			break;
-		case WAIT_EVENT_HASH_BUILD_ALLOCATE:
-			event_name = "HashBuildAllocate";
-			break;
-		case WAIT_EVENT_HASH_BUILD_ELECT:
-			event_name = "HashBuildElect";
-			break;
-		case WAIT_EVENT_HASH_BUILD_HASH_INNER:
-			event_name = "HashBuildHashInner";
-			break;
-		case WAIT_EVENT_HASH_BUILD_HASH_OUTER:
-			event_name = "HashBuildHashOuter";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_DECIDE:
-			event_name = "HashGrowBatchesDecide";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_ELECT:
-			event_name = "HashGrowBatchesElect";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_FINISH:
-			event_name = "HashGrowBatchesFinish";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_REALLOCATE:
-			event_name = "HashGrowBatchesReallocate";
-			break;
-		case WAIT_EVENT_HASH_GROW_BATCHES_REPARTITION:
-			event_name = "HashGrowBatchesRepartition";
-			break;
-		case WAIT_EVENT_HASH_GROW_BUCKETS_ELECT:
-			event_name = "HashGrowBucketsElect";
-			break;
-		case WAIT_EVENT_HASH_GROW_BUCKETS_REALLOCATE:
-			event_name = "HashGrowBucketsReallocate";
-			break;
-		case WAIT_EVENT_HASH_GROW_BUCKETS_REINSERT:
-			event_name = "HashGrowBucketsReinsert";
-			break;
-		case WAIT_EVENT_LOGICAL_APPLY_SEND_DATA:
-			event_name = "LogicalApplySendData";
-			break;
-		case WAIT_EVENT_LOGICAL_PARALLEL_APPLY_STATE_CHANGE:
-			event_name = "LogicalParallelApplyStateChange";
-			break;
-		case WAIT_EVENT_LOGICAL_SYNC_DATA:
-			event_name = "LogicalSyncData";
-			break;
-		case WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE:
-			event_name = "LogicalSyncStateChange";
-			break;
-		case WAIT_EVENT_MQ_INTERNAL:
-			event_name = "MessageQueueInternal";
-			break;
-		case WAIT_EVENT_MQ_PUT_MESSAGE:
-			event_name = "MessageQueuePutMessage";
-			break;
-		case WAIT_EVENT_MQ_RECEIVE:
-			event_name = "MessageQueueReceive";
-			break;
-		case WAIT_EVENT_MQ_SEND:
-			event_name = "MessageQueueSend";
-			break;
-		case WAIT_EVENT_PARALLEL_BITMAP_SCAN:
-			event_name = "ParallelBitmapScan";
-			break;
-		case WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN:
-			event_name = "ParallelCreateIndexScan";
-			break;
-		case WAIT_EVENT_PARALLEL_FINISH:
-			event_name = "ParallelFinish";
-			break;
-		case WAIT_EVENT_PROCARRAY_GROUP_UPDATE:
-			event_name = "ProcArrayGroupUpdate";
-			break;
-		case WAIT_EVENT_PROC_SIGNAL_BARRIER:
-			event_name = "ProcSignalBarrier";
-			break;
-		case WAIT_EVENT_PROMOTE:
-			event_name = "Promote";
-			break;
-		case WAIT_EVENT_RECOVERY_CONFLICT_SNAPSHOT:
-			event_name = "RecoveryConflictSnapshot";
-			break;
-		case WAIT_EVENT_RECOVERY_CONFLICT_TABLESPACE:
-			event_name = "RecoveryConflictTablespace";
-			break;
-		case WAIT_EVENT_RECOVERY_END_COMMAND:
-			event_name = "RecoveryEndCommand";
-			break;
-		case WAIT_EVENT_RECOVERY_PAUSE:
-			event_name = "RecoveryPause";
-			break;
-		case WAIT_EVENT_REPLICATION_ORIGIN_DROP:
-			event_name = "ReplicationOriginDrop";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_DROP:
-			event_name = "ReplicationSlotDrop";
-			break;
-		case WAIT_EVENT_RESTORE_COMMAND:
-			event_name = "RestoreCommand";
-			break;
-		case WAIT_EVENT_SAFE_SNAPSHOT:
-			event_name = "SafeSnapshot";
-			break;
-		case WAIT_EVENT_SYNC_REP:
-			event_name = "SyncRep";
-			break;
-		case WAIT_EVENT_WAL_RECEIVER_EXIT:
-			event_name = "WalReceiverExit";
-			break;
-		case WAIT_EVENT_WAL_RECEIVER_WAIT_START:
-			event_name = "WalReceiverWaitStart";
-			break;
-		case WAIT_EVENT_XACT_GROUP_UPDATE:
-			event_name = "XactGroupUpdate";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_timeout() -
- *
- * Convert WaitEventTimeout to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_timeout(WaitEventTimeout w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_BASE_BACKUP_THROTTLE:
-			event_name = "BaseBackupThrottle";
-			break;
-		case WAIT_EVENT_CHECKPOINT_WRITE_DELAY:
-			event_name = "CheckpointWriteDelay";
-			break;
-		case WAIT_EVENT_PG_SLEEP:
-			event_name = "PgSleep";
-			break;
-		case WAIT_EVENT_RECOVERY_APPLY_DELAY:
-			event_name = "RecoveryApplyDelay";
-			break;
-		case WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL:
-			event_name = "RecoveryRetrieveRetryInterval";
-			break;
-		case WAIT_EVENT_REGISTER_SYNC_REQUEST:
-			event_name = "RegisterSyncRequest";
-			break;
-		case WAIT_EVENT_SPIN_DELAY:
-			event_name = "SpinDelay";
-			break;
-		case WAIT_EVENT_VACUUM_DELAY:
-			event_name = "VacuumDelay";
-			break;
-		case WAIT_EVENT_VACUUM_TRUNCATE:
-			event_name = "VacuumTruncate";
-			break;
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
-
-/* ----------
- * pgstat_get_wait_io() -
- *
- * Convert WaitEventIO to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_io(WaitEventIO w)
-{
-	const char *event_name = "unknown wait event";
-
-	switch (w)
-	{
-		case WAIT_EVENT_BASEBACKUP_READ:
-			event_name = "BaseBackupRead";
-			break;
-		case WAIT_EVENT_BASEBACKUP_SYNC:
-			event_name = "BaseBackupSync";
-			break;
-		case WAIT_EVENT_BASEBACKUP_WRITE:
-			event_name = "BaseBackupWrite";
-			break;
-		case WAIT_EVENT_BUFFILE_READ:
-			event_name = "BufFileRead";
-			break;
-		case WAIT_EVENT_BUFFILE_WRITE:
-			event_name = "BufFileWrite";
-			break;
-		case WAIT_EVENT_BUFFILE_TRUNCATE:
-			event_name = "BufFileTruncate";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_READ:
-			event_name = "ControlFileRead";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_SYNC:
-			event_name = "ControlFileSync";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE:
-			event_name = "ControlFileSyncUpdate";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_WRITE:
-			event_name = "ControlFileWrite";
-			break;
-		case WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE:
-			event_name = "ControlFileWriteUpdate";
-			break;
-		case WAIT_EVENT_COPY_FILE_READ:
-			event_name = "CopyFileRead";
-			break;
-		case WAIT_EVENT_COPY_FILE_WRITE:
-			event_name = "CopyFileWrite";
-			break;
-		case WAIT_EVENT_DATA_FILE_EXTEND:
-			event_name = "DataFileExtend";
-			break;
-		case WAIT_EVENT_DATA_FILE_FLUSH:
-			event_name = "DataFileFlush";
-			break;
-		case WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC:
-			event_name = "DataFileImmediateSync";
-			break;
-		case WAIT_EVENT_DATA_FILE_PREFETCH:
-			event_name = "DataFilePrefetch";
-			break;
-		case WAIT_EVENT_DATA_FILE_READ:
-			event_name = "DataFileRead";
-			break;
-		case WAIT_EVENT_DATA_FILE_SYNC:
-			event_name = "DataFileSync";
-			break;
-		case WAIT_EVENT_DATA_FILE_TRUNCATE:
-			event_name = "DataFileTruncate";
-			break;
-		case WAIT_EVENT_DATA_FILE_WRITE:
-			event_name = "DataFileWrite";
-			break;
-		case WAIT_EVENT_DSM_ALLOCATE:
-			event_name = "DSMAllocate";
-			break;
-		case WAIT_EVENT_DSM_FILL_ZERO_WRITE:
-			event_name = "DSMFillZeroWrite";
-			break;
-		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ:
-			event_name = "LockFileAddToDataDirRead";
-			break;
-		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC:
-			event_name = "LockFileAddToDataDirSync";
-			break;
-		case WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE:
-			event_name = "LockFileAddToDataDirWrite";
-			break;
-		case WAIT_EVENT_LOCK_FILE_CREATE_READ:
-			event_name = "LockFileCreateRead";
-			break;
-		case WAIT_EVENT_LOCK_FILE_CREATE_SYNC:
-			event_name = "LockFileCreateSync";
-			break;
-		case WAIT_EVENT_LOCK_FILE_CREATE_WRITE:
-			event_name = "LockFileCreateWrite";
-			break;
-		case WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ:
-			event_name = "LockFileReCheckDataDirRead";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC:
-			event_name = "LogicalRewriteCheckpointSync";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC:
-			event_name = "LogicalRewriteMappingSync";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE:
-			event_name = "LogicalRewriteMappingWrite";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_SYNC:
-			event_name = "LogicalRewriteSync";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE:
-			event_name = "LogicalRewriteTruncate";
-			break;
-		case WAIT_EVENT_LOGICAL_REWRITE_WRITE:
-			event_name = "LogicalRewriteWrite";
-			break;
-		case WAIT_EVENT_RELATION_MAP_READ:
-			event_name = "RelationMapRead";
-			break;
-		case WAIT_EVENT_RELATION_MAP_REPLACE:
-			event_name = "RelationMapReplace";
-			break;
-		case WAIT_EVENT_RELATION_MAP_WRITE:
-			event_name = "RelationMapWrite";
-			break;
-		case WAIT_EVENT_REORDER_BUFFER_READ:
-			event_name = "ReorderBufferRead";
-			break;
-		case WAIT_EVENT_REORDER_BUFFER_WRITE:
-			event_name = "ReorderBufferWrite";
-			break;
-		case WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ:
-			event_name = "ReorderLogicalMappingRead";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_READ:
-			event_name = "ReplicationSlotRead";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC:
-			event_name = "ReplicationSlotRestoreSync";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_SYNC:
-			event_name = "ReplicationSlotSync";
-			break;
-		case WAIT_EVENT_REPLICATION_SLOT_WRITE:
-			event_name = "ReplicationSlotWrite";
-			break;
-		case WAIT_EVENT_SLRU_FLUSH_SYNC:
-			event_name = "SLRUFlushSync";
-			break;
-		case WAIT_EVENT_SLRU_READ:
-			event_name = "SLRURead";
-			break;
-		case WAIT_EVENT_SLRU_SYNC:
-			event_name = "SLRUSync";
-			break;
-		case WAIT_EVENT_SLRU_WRITE:
-			event_name = "SLRUWrite";
-			break;
-		case WAIT_EVENT_SNAPBUILD_READ:
-			event_name = "SnapbuildRead";
-			break;
-		case WAIT_EVENT_SNAPBUILD_SYNC:
-			event_name = "SnapbuildSync";
-			break;
-		case WAIT_EVENT_SNAPBUILD_WRITE:
-			event_name = "SnapbuildWrite";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC:
-			event_name = "TimelineHistoryFileSync";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE:
-			event_name = "TimelineHistoryFileWrite";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_READ:
-			event_name = "TimelineHistoryRead";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_SYNC:
-			event_name = "TimelineHistorySync";
-			break;
-		case WAIT_EVENT_TIMELINE_HISTORY_WRITE:
-			event_name = "TimelineHistoryWrite";
-			break;
-		case WAIT_EVENT_TWOPHASE_FILE_READ:
-			event_name = "TwophaseFileRead";
-			break;
-		case WAIT_EVENT_TWOPHASE_FILE_SYNC:
-			event_name = "TwophaseFileSync";
-			break;
-		case WAIT_EVENT_TWOPHASE_FILE_WRITE:
-			event_name = "TwophaseFileWrite";
-			break;
-		case WAIT_EVENT_VERSION_FILE_WRITE:
-			event_name = "VersionFileWrite";
-			break;
-		case WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ:
-			event_name = "WALSenderTimelineHistoryRead";
-			break;
-		case WAIT_EVENT_WAL_BOOTSTRAP_SYNC:
-			event_name = "WALBootstrapSync";
-			break;
-		case WAIT_EVENT_WAL_BOOTSTRAP_WRITE:
-			event_name = "WALBootstrapWrite";
-			break;
-		case WAIT_EVENT_WAL_COPY_READ:
-			event_name = "WALCopyRead";
-			break;
-		case WAIT_EVENT_WAL_COPY_SYNC:
-			event_name = "WALCopySync";
-			break;
-		case WAIT_EVENT_WAL_COPY_WRITE:
-			event_name = "WALCopyWrite";
-			break;
-		case WAIT_EVENT_WAL_INIT_SYNC:
-			event_name = "WALInitSync";
-			break;
-		case WAIT_EVENT_WAL_INIT_WRITE:
-			event_name = "WALInitWrite";
-			break;
-		case WAIT_EVENT_WAL_READ:
-			event_name = "WALRead";
-			break;
-		case WAIT_EVENT_WAL_SYNC:
-			event_name = "WALSync";
-			break;
-		case WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN:
-			event_name = "WALSyncMethodAssign";
-			break;
-		case WAIT_EVENT_WAL_WRITE:
-			event_name = "WALWrite";
-			break;
-
-			/* no default case, so that compiler will warn */
-	}
-
-	return event_name;
-}
+#include "pgstat_wait_event.c"
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
new file mode 100644
index 0000000000..2e744ea8c7
--- /dev/null
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -0,0 +1,371 @@
+#
+# wait_event_names.txt
+#      PostgreSQL wait events
+#
+# Copyright (c) 2023, PostgreSQL Global Development Group
+#
+# This list serves as the basis for generating source and documentation files
+# related to wait events.
+#
+# The files generated from this one are:
+#
+#   src/backend/utils/activity/wait_event_types.h
+#      typedef enum definitions for wait events.
+#
+#   src/backend/utils/activity/pgstat_wait_event.c
+#      C functions to get the wait event name based on the enum.
+#
+#   src/backend/utils/activity/wait_event_types.sgml
+#      SGML tables of wait events for inclusion in the documentation.
+#
+# This file defines one wait event per line, with the three following
+# tab-separated fields:
+#
+#      "C symbol in enums" "format in the system views" "description in the docs"
+#
+# When adding a new wait event, make sure it is placed in the appropriate
+# ClassName section.
+#
+# WaitEventLWLock and WaitEventLock have their own C code for their wait event
+# enums and function names.  Hence, for these, only the SGML documentation is
+# generated.
+#
+# This file is fed to src/backend/utils/activity/generate-wait_event_types.pl.
+#
+
+
+#
+# Wait Events - Activity
+#
+# Use this category when a process is waiting because it has no work to do,
+# unless the "Client" or "Timeout" category describes the situation better.
+# Typically, this should only be used for background processes.
+#
+
+Section: ClassName - WaitEventActivity
+
+WAIT_EVENT_ARCHIVER_MAIN	"ArchiverMain"	"Waiting in main loop of archiver process."
+WAIT_EVENT_AUTOVACUUM_MAIN	"AutoVacuumMain"	"Waiting in main loop of autovacuum launcher process."
+WAIT_EVENT_BGWRITER_HIBERNATE	"BgWriterHibernate"	"Waiting in background writer process, hibernating."
+WAIT_EVENT_BGWRITER_MAIN	"BgWriterMain"	"Waiting in main loop of background writer process."
+WAIT_EVENT_CHECKPOINTER_MAIN	"CheckpointerMain"	"Waiting in main loop of checkpointer process."
+WAIT_EVENT_LOGICAL_APPLY_MAIN	"LogicalApplyMain"	"Waiting in main loop of logical replication apply process."
+WAIT_EVENT_LOGICAL_LAUNCHER_MAIN	"LogicalLauncherMain"	"Waiting in main loop of logical replication launcher process."
+WAIT_EVENT_LOGICAL_PARALLEL_APPLY_MAIN	"LogicalParallelApplyMain"	"Waiting in main loop of logical replication parallel apply process."
+WAIT_EVENT_RECOVERY_WAL_STREAM	"RecoveryWalStream"	"Waiting in main loop of startup process for WAL to arrive, during streaming recovery."
+WAIT_EVENT_SYSLOGGER_MAIN	"SysLoggerMain"	"Waiting in main loop of syslogger process."
+WAIT_EVENT_WAL_RECEIVER_MAIN	"WalReceiverMain"	"Waiting in main loop of WAL receiver process."
+WAIT_EVENT_WAL_SENDER_MAIN	"WalSenderMain"	"Waiting in main loop of WAL sender process."
+WAIT_EVENT_WAL_WRITER_MAIN	"WalWriterMain"	"Waiting in main loop of WAL writer process."
+
+
+#
+# Wait Events - Client
+#
+# Use this category when a process is waiting to send data to or receive data
+# from the frontend process to which it is connected.  This is never used for
+# a background process, which has no client connection.
+#
+
+Section: ClassName - WaitEventClient
+
+WAIT_EVENT_CLIENT_READ	"ClientRead"	"Waiting to read data from the client."
+WAIT_EVENT_CLIENT_WRITE	"ClientWrite"	"Waiting to write data to the client."
+WAIT_EVENT_GSS_OPEN_SERVER	"GSSOpenServer"	"Waiting to read data from the client while establishing a GSSAPI session."
+WAIT_EVENT_LIBPQWALRECEIVER_CONNECT	"LibPQWalReceiverConnect"	"Waiting in WAL receiver to establish connection to remote server."
+WAIT_EVENT_LIBPQWALRECEIVER_RECEIVE	"LibPQWalReceiverReceive"	"Waiting in WAL receiver to receive data from remote server."
+WAIT_EVENT_SSL_OPEN_SERVER	"SSLOpenServer"	"Waiting for SSL while attempting connection."
+WAIT_EVENT_WAL_SENDER_WAIT_WAL	"WalSenderWaitForWAL"	"Waiting for WAL to be flushed in WAL sender process."
+WAIT_EVENT_WAL_SENDER_WRITE_DATA	"WalSenderWriteData"	"Waiting for any activity when processing replies from WAL receiver in WAL sender process."
+
+
+#
+# Wait Events - IPC
+#
+# Use this category when a process cannot complete the work it is doing because
+# it is waiting for a notification from another process.
+#
+
+Section: ClassName - WaitEventIPC
+
+WAIT_EVENT_APPEND_READY	"AppendReady"	"Waiting for subplan nodes of an <literal>Append</literal> plan node to be ready."
+WAIT_EVENT_ARCHIVE_CLEANUP_COMMAND	"ArchiveCleanupCommand"	"Waiting for <xref linkend="guc-archive-cleanup-command"/> to complete."
+WAIT_EVENT_ARCHIVE_COMMAND	"ArchiveCommand"	"Waiting for <xref linkend="guc-archive-command"/> to complete."
+WAIT_EVENT_BACKEND_TERMINATION	"BackendTermination"	"Waiting for the termination of another backend."
+WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE	"BackupWaitWalArchive"	"Waiting for WAL files required for a backup to be successfully archived."
+WAIT_EVENT_BGWORKER_SHUTDOWN	"BgWorkerShutdown"	"Waiting for background worker to shut down."
+WAIT_EVENT_BGWORKER_STARTUP	"BgWorkerStartup"	"Waiting for background worker to start up."
+WAIT_EVENT_BTREE_PAGE	"BtreePage"	"Waiting for the page number needed to continue a parallel B-tree scan to become available."
+WAIT_EVENT_BUFFER_IO	"BufferIO"	"Waiting for buffer I/O to complete."
+WAIT_EVENT_CHECKPOINT_DONE	"CheckpointDone"	"Waiting for a checkpoint to complete."
+WAIT_EVENT_CHECKPOINT_START	"CheckpointStart"	"Waiting for a checkpoint to start."
+WAIT_EVENT_EXECUTE_GATHER	"ExecuteGather"	"Waiting for activity from a child process while executing a <literal>Gather</literal> plan node."
+WAIT_EVENT_HASH_BATCH_ALLOCATE	"HashBatchAllocate"	"Waiting for an elected Parallel Hash participant to allocate a hash table."
+WAIT_EVENT_HASH_BATCH_ELECT	"HashBatchElect"	"Waiting to elect a Parallel Hash participant to allocate a hash table."
+WAIT_EVENT_HASH_BATCH_LOAD	"HashBatchLoad"	"Waiting for other Parallel Hash participants to finish loading a hash table."
+WAIT_EVENT_HASH_BUILD_ALLOCATE	"HashBuildAllocate"	"Waiting for an elected Parallel Hash participant to allocate the initial hash table."
+WAIT_EVENT_HASH_BUILD_ELECT	"HashBuildElect"	"Waiting to elect a Parallel Hash participant to allocate the initial hash table."
+WAIT_EVENT_HASH_BUILD_HASH_INNER	"HashBuildHashInner"	"Waiting for other Parallel Hash participants to finish hashing the inner relation."
+WAIT_EVENT_HASH_BUILD_HASH_OUTER	"HashBuildHashOuter"	"Waiting for other Parallel Hash participants to finish partitioning the outer relation."
+WAIT_EVENT_HASH_GROW_BATCHES_DECIDE	"HashGrowBatchesDecide"	"Waiting to elect a Parallel Hash participant to decide on future batch growth."
+WAIT_EVENT_HASH_GROW_BATCHES_ELECT	"HashGrowBatchesElect"	"Waiting to elect a Parallel Hash participant to allocate more batches."
+WAIT_EVENT_HASH_GROW_BATCHES_FINISH	"HashGrowBatchesFinish"	"Waiting for an elected Parallel Hash participant to decide on future batch growth."
+WAIT_EVENT_HASH_GROW_BATCHES_REALLOCATE	"HashGrowBatchesReallocate"	"Waiting for an elected Parallel Hash participant to allocate more batches."
+WAIT_EVENT_HASH_GROW_BATCHES_REPARTITION	"HashGrowBatchesRepartition"	"Waiting for other Parallel Hash participants to finish repartitioning."
+WAIT_EVENT_HASH_GROW_BUCKETS_ELECT	"HashGrowBucketsElect"	"Waiting to elect a Parallel Hash participant to allocate more buckets."
+WAIT_EVENT_HASH_GROW_BUCKETS_REALLOCATE	"HashGrowBucketsReallocate"	"Waiting for an elected Parallel Hash participant to finish allocating more buckets."
+WAIT_EVENT_HASH_GROW_BUCKETS_REINSERT	"HashGrowBucketsReinsert"	"Waiting for other Parallel Hash participants to finish inserting tuples into new buckets."
+WAIT_EVENT_LOGICAL_APPLY_SEND_DATA	"LogicalApplySendData"	"Waiting for a logical replication leader apply process to send data to a parallel apply process."
+WAIT_EVENT_LOGICAL_PARALLEL_APPLY_STATE_CHANGE	"LogicalParallelApplyStateChange"	"Waiting for a logical replication parallel apply process to change state."
+WAIT_EVENT_LOGICAL_SYNC_DATA	"LogicalSyncData"	"Waiting for a logical replication remote server to send data for initial table synchronization."
+WAIT_EVENT_LOGICAL_SYNC_STATE_CHANGE	"LogicalSyncStateChange"	"Waiting for a logical replication remote server to change state."
+WAIT_EVENT_MQ_INTERNAL	"MessageQueueInternal"	"Waiting for another process to be attached to a shared message queue."
+WAIT_EVENT_MQ_PUT_MESSAGE	"MessageQueuePutMessage"	"Waiting to write a protocol message to a shared message queue."
+WAIT_EVENT_MQ_RECEIVE	"MessageQueueReceive"	"Waiting to receive bytes from a shared message queue."
+WAIT_EVENT_MQ_SEND	"MessageQueueSend"	"Waiting to send bytes to a shared message queue."
+WAIT_EVENT_PARALLEL_BITMAP_SCAN	"ParallelBitmapScan"	"Waiting for parallel bitmap scan to become initialized."
+WAIT_EVENT_PARALLEL_CREATE_INDEX_SCAN	"ParallelCreateIndexScan"	"Waiting for parallel <command>CREATE INDEX</command> workers to finish heap scan."
+WAIT_EVENT_PARALLEL_FINISH	"ParallelFinish"	"Waiting for parallel workers to finish computing."
+WAIT_EVENT_PROCARRAY_GROUP_UPDATE	"ProcArrayGroupUpdate"	"Waiting for the group leader to clear the transaction ID at end of a parallel operation."
+WAIT_EVENT_PROC_SIGNAL_BARRIER	"ProcSignalBarrier"	"Waiting for a barrier event to be processed by all backends."
+WAIT_EVENT_PROMOTE	"Promote"	"Waiting for standby promotion."
+WAIT_EVENT_RECOVERY_CONFLICT_SNAPSHOT	"RecoveryConflictSnapshot"	"Waiting for recovery conflict resolution for a vacuum cleanup."
+WAIT_EVENT_RECOVERY_CONFLICT_TABLESPACE	"RecoveryConflictTablespace"	"Waiting for recovery conflict resolution for dropping a tablespace."
+WAIT_EVENT_RECOVERY_END_COMMAND	"RecoveryEndCommand"	"Waiting for <xref linkend="guc-recovery-end-command"/> to complete."
+WAIT_EVENT_RECOVERY_PAUSE	"RecoveryPause"	"Waiting for recovery to be resumed."
+WAIT_EVENT_REPLICATION_ORIGIN_DROP	"ReplicationOriginDrop"	"Waiting for a replication origin to become inactive so it can be dropped."
+WAIT_EVENT_REPLICATION_SLOT_DROP	"ReplicationSlotDrop"	"Waiting for a replication slot to become inactive so it can be dropped."
+WAIT_EVENT_RESTORE_COMMAND	"RestoreCommand"	"Waiting for <xref linkend="guc-restore-command"/> to complete."
+WAIT_EVENT_SAFE_SNAPSHOT	"SafeSnapshot"	"Waiting to obtain a valid snapshot for a <literal>READ ONLY DEFERRABLE</literal> transaction."
+WAIT_EVENT_SYNC_REP	"SyncRep"	"Waiting for confirmation from a remote server during synchronous replication. Waiting to read or update information about the state of synchronous replication."
+WAIT_EVENT_WAL_RECEIVER_EXIT	"WalReceiverExit"	"Waiting for the WAL receiver to exit."
+WAIT_EVENT_WAL_RECEIVER_WAIT_START	"WalReceiverWaitStart"	"Waiting for startup process to send initial data for streaming replication."
+WAIT_EVENT_XACT_GROUP_UPDATE	"XactGroupUpdate"	"Waiting for the group leader to update transaction status at end of a parallel operation."
+
+
+#
+# Wait Events - Timeout
+#
+# Use this category when a process is waiting for a timeout to expire.
+#
+
+Section: ClassName - WaitEventTimeout
+
+WAIT_EVENT_BASE_BACKUP_THROTTLE	"BaseBackupThrottle"	"Waiting during base backup when throttling activity."
+WAIT_EVENT_CHECKPOINT_WRITE_DELAY	"CheckpointWriteDelay"	"Waiting between writes while performing a checkpoint."
+WAIT_EVENT_PG_SLEEP	"PgSleep"	"Waiting due to a call to <function>pg_sleep</function> or a sibling function."
+WAIT_EVENT_RECOVERY_APPLY_DELAY	"RecoveryApplyDelay"	"Waiting to apply WAL during recovery because of a delay setting."
+WAIT_EVENT_RECOVERY_RETRIEVE_RETRY_INTERVAL	"RecoveryRetrieveRetryInterval"	"Waiting during recovery when WAL data is not available from any source (<filename>pg_wal</filename>, archive or stream)."
+WAIT_EVENT_REGISTER_SYNC_REQUEST	"RegisterSyncRequest"	"Waiting while sending synchronization requests to the checkpointer, because the request queue is full."
+WAIT_EVENT_SPIN_DELAY	"SpinDelay"	"Waiting while acquiring a contended spinlock."
+WAIT_EVENT_VACUUM_DELAY	"VacuumDelay"	"Waiting in a cost-based vacuum delay point."
+WAIT_EVENT_VACUUM_TRUNCATE	"VacuumTruncate"	"Waiting to acquire an exclusive lock to truncate off any empty pages at the end of a table vacuumed."
+
+
+#
+# Wait Events - IO
+#
+# Use this category when a process is waiting for a IO.
+#
+
+Section: ClassName - WaitEventIO
+
+WAIT_EVENT_BASEBACKUP_READ	"BaseBackupRead"	"Waiting for base backup to read from a file."
+WAIT_EVENT_BASEBACKUP_SYNC	"BaseBackupSync"	"Waiting for data written by a base backup to reach durable storage."
+WAIT_EVENT_BASEBACKUP_WRITE	"BaseBackupWrite"	"Waiting for base backup to write to a file."
+WAIT_EVENT_BUFFILE_READ	"BufFileRead"	"Waiting for a read from a buffered file."
+WAIT_EVENT_BUFFILE_WRITE	"BufFileWrite"	"Waiting for a write to a buffered file."
+WAIT_EVENT_BUFFILE_TRUNCATE	"BufFileTruncate"	"Waiting for a buffered file to be truncated."
+WAIT_EVENT_CONTROL_FILE_READ	"ControlFileRead"	"Waiting for a read from the <filename>pg_control</filename> file."
+WAIT_EVENT_CONTROL_FILE_SYNC	"ControlFileSync"	"Waiting for the <filename>pg_control</filename> file to reach durable storage. Waiting for an update to the <filename>pg_control</filename> file to reach durable storage."
+WAIT_EVENT_CONTROL_FILE_SYNC_UPDATE	"ControlFileSyncUpdate"	"Waiting for an update to the <filename>pg_control</filename> file to reach durable storage."
+WAIT_EVENT_CONTROL_FILE_WRITE	"ControlFileWrite"	"Waiting for a write to the <filename>pg_control</filename> file. Waiting for a write to update the <filename>pg_control</filename> file."
+WAIT_EVENT_CONTROL_FILE_WRITE_UPDATE	"ControlFileWriteUpdate"	"Waiting for a write to update the <filename>pg_control</filename> file."
+WAIT_EVENT_COPY_FILE_READ	"CopyFileRead"	"Waiting for a read during a file copy operation."
+WAIT_EVENT_COPY_FILE_WRITE	"CopyFileWrite"	"Waiting for a write during a file copy operation."
+WAIT_EVENT_DATA_FILE_EXTEND	"DataFileExtend"	"Waiting for a relation data file to be extended."
+WAIT_EVENT_DATA_FILE_FLUSH	"DataFileFlush"	"Waiting for a relation data file to reach durable storage."
+WAIT_EVENT_DATA_FILE_IMMEDIATE_SYNC	"DataFileImmediateSync"	"Waiting for an immediate synchronization of a relation data file to durable storage."
+WAIT_EVENT_DATA_FILE_PREFETCH	"DataFilePrefetch"	"Waiting for an asynchronous prefetch from a relation data file."
+WAIT_EVENT_DATA_FILE_READ	"DataFileRead"	"Waiting for a read from a relation data file."
+WAIT_EVENT_DATA_FILE_SYNC	"DataFileSync"	"Waiting for changes to a relation data file to reach durable storage."
+WAIT_EVENT_DATA_FILE_TRUNCATE	"DataFileTruncate"	"Waiting for a relation data file to be truncated."
+WAIT_EVENT_DATA_FILE_WRITE	"DataFileWrite"	"Waiting for a write to a relation data file."
+WAIT_EVENT_DSM_ALLOCATE	"DSMAllocate"	"Waiting for a dynamic shared memory segment to be allocated."
+WAIT_EVENT_DSM_FILL_ZERO_WRITE	"DSMFillZeroWrite"	"Waiting to fill a dynamic shared memory backing file with zeroes."
+WAIT_EVENT_LOCK_FILE_ADDTODATADIR_READ	"LockFileAddToDataDirRead"	"Waiting for a read while adding a line to the data directory lock file."
+WAIT_EVENT_LOCK_FILE_ADDTODATADIR_SYNC	"LockFileAddToDataDirSync"	"Waiting for data to reach durable storage while adding a line to the data directory lock file."
+WAIT_EVENT_LOCK_FILE_ADDTODATADIR_WRITE	"LockFileAddToDataDirWrite"	"Waiting for a write while adding a line to the data directory lock file."
+WAIT_EVENT_LOCK_FILE_CREATE_READ	"LockFileCreateRead"	"Waiting to read while creating the data directory lock file."
+WAIT_EVENT_LOCK_FILE_CREATE_SYNC	"LockFileCreateSync"	"Waiting for data to reach durable storage while creating the data directory lock file."
+WAIT_EVENT_LOCK_FILE_CREATE_WRITE	"LockFileCreateWrite"	"Waiting for a write while creating the data directory lock file."
+WAIT_EVENT_LOCK_FILE_RECHECKDATADIR_READ	"LockFileReCheckDataDirRead"	"Waiting for a read during recheck of the data directory lock file."
+WAIT_EVENT_LOGICAL_REWRITE_CHECKPOINT_SYNC	"LogicalRewriteCheckpointSync"	"Waiting for logical rewrite mappings to reach durable storage during a checkpoint."
+WAIT_EVENT_LOGICAL_REWRITE_MAPPING_SYNC	"LogicalRewriteMappingSync"	"Waiting for mapping data to reach durable storage during a logical rewrite."
+WAIT_EVENT_LOGICAL_REWRITE_MAPPING_WRITE	"LogicalRewriteMappingWrite"	"Waiting for a write of mapping data during a logical rewrite."
+WAIT_EVENT_LOGICAL_REWRITE_SYNC	"LogicalRewriteSync"	"Waiting for logical rewrite mappings to reach durable storage."
+WAIT_EVENT_LOGICAL_REWRITE_TRUNCATE	"LogicalRewriteTruncate"	"Waiting for truncate of mapping data during a logical rewrite."
+WAIT_EVENT_LOGICAL_REWRITE_WRITE	"LogicalRewriteWrite"	"Waiting for a write of logical rewrite mappings."
+WAIT_EVENT_RELATION_MAP_READ	"RelationMapRead"	"Waiting for a read of the relation map file."
+WAIT_EVENT_RELATION_MAP_REPLACE	"RelationMapReplace"	"Waiting for durable replacement of a relation map file."
+WAIT_EVENT_RELATION_MAP_WRITE	"RelationMapWrite"	"Waiting for a write to the relation map file."
+WAIT_EVENT_REORDER_BUFFER_READ	"ReorderBufferRead"	"Waiting for a read during reorder buffer management."
+WAIT_EVENT_REORDER_BUFFER_WRITE	"ReorderBufferWrite"	"Waiting for a write during reorder buffer management."
+WAIT_EVENT_REORDER_LOGICAL_MAPPING_READ	"ReorderLogicalMappingRead"	"Waiting for a read of a logical mapping during reorder buffer management."
+WAIT_EVENT_REPLICATION_SLOT_READ	"ReplicationSlotRead"	"Waiting for a read from a replication slot control file."
+WAIT_EVENT_REPLICATION_SLOT_RESTORE_SYNC	"ReplicationSlotRestoreSync"	"Waiting for a replication slot control file to reach durable storage while restoring it to memory."
+WAIT_EVENT_REPLICATION_SLOT_SYNC	"ReplicationSlotSync"	"Waiting for a replication slot control file to reach durable storage."
+WAIT_EVENT_REPLICATION_SLOT_WRITE	"ReplicationSlotWrite"	"Waiting for a write to a replication slot control file."
+WAIT_EVENT_SLRU_FLUSH_SYNC	"SLRUFlushSync"	"Waiting for SLRU data to reach durable storage during a checkpoint or database shutdown."
+WAIT_EVENT_SLRU_READ	"SLRURead"	"Waiting for a read of an SLRU page."
+WAIT_EVENT_SLRU_SYNC	"SLRUSync"	"Waiting for SLRU data to reach durable storage following a page write."
+WAIT_EVENT_SLRU_WRITE	"SLRUWrite"	"Waiting for a write of an SLRU page."
+WAIT_EVENT_SNAPBUILD_READ	"SnapbuildRead"	"Waiting for a read of a serialized historical catalog snapshot."
+WAIT_EVENT_SNAPBUILD_SYNC	"SnapbuildSync"	"Waiting for a serialized historical catalog snapshot to reach durable storage."
+WAIT_EVENT_SNAPBUILD_WRITE	"SnapbuildWrite"	"Waiting for a write of a serialized historical catalog snapshot."
+WAIT_EVENT_TIMELINE_HISTORY_FILE_SYNC	"TimelineHistoryFileSync"	"Waiting for a timeline history file received via streaming replication to reach durable storage."
+WAIT_EVENT_TIMELINE_HISTORY_FILE_WRITE	"TimelineHistoryFileWrite"	"Waiting for a write of a timeline history file received via streaming replication."
+WAIT_EVENT_TIMELINE_HISTORY_READ	"TimelineHistoryRead"	"Waiting for a read of a timeline history file."
+WAIT_EVENT_TIMELINE_HISTORY_SYNC	"TimelineHistorySync"	"Waiting for a newly created timeline history file to reach durable storage."
+WAIT_EVENT_TIMELINE_HISTORY_WRITE	"TimelineHistoryWrite"	"Waiting for a write of a newly created timeline history file."
+WAIT_EVENT_TWOPHASE_FILE_READ	"TwophaseFileRead"	"Waiting for a read of a two phase state file."
+WAIT_EVENT_TWOPHASE_FILE_SYNC	"TwophaseFileSync"	"Waiting for a two phase state file to reach durable storage."
+WAIT_EVENT_TWOPHASE_FILE_WRITE	"TwophaseFileWrite"	"Waiting for a write of a two phase state file."
+WAIT_EVENT_VERSION_FILE_WRITE	"VersionFileWrite"	"Waiting for the version file to be written while creating a database."
+WAIT_EVENT_WALSENDER_TIMELINE_HISTORY_READ	"WALSenderTimelineHistoryRead"	"Waiting for a read from a timeline history file during a walsender timeline command."
+WAIT_EVENT_WAL_BOOTSTRAP_SYNC	"WALBootstrapSync"	"Waiting for WAL to reach durable storage during bootstrapping."
+WAIT_EVENT_WAL_BOOTSTRAP_WRITE	"WALBootstrapWrite"	"Waiting for a write of a WAL page during bootstrapping."
+WAIT_EVENT_WAL_COPY_READ	"WALCopyRead"	"Waiting for a read when creating a new WAL segment by copying an existing one."
+WAIT_EVENT_WAL_COPY_SYNC	"WALCopySync"	"Waiting for a new WAL segment created by copying an existing one to reach durable storage."
+WAIT_EVENT_WAL_COPY_WRITE	"WALCopyWrite"	"Waiting for a write when creating a new WAL segment by copying an existing one."
+WAIT_EVENT_WAL_INIT_SYNC	"WALInitSync"	"Waiting for a newly initialized WAL file to reach durable storage."
+WAIT_EVENT_WAL_INIT_WRITE	"WALInitWrite"	"Waiting for a write while initializing a new WAL file."
+WAIT_EVENT_WAL_READ	"WALRead"	"Waiting for a read from a WAL file."
+WAIT_EVENT_WAL_SYNC	"WALSync"	"Waiting for a WAL file to reach durable storage. Waiting for data to reach durable storage while assigning a new WAL sync method."
+WAIT_EVENT_WAL_SYNC_METHOD_ASSIGN	"WALSyncMethodAssign"	"Waiting for data to reach durable storage while assigning a new WAL sync method."
+WAIT_EVENT_WAL_WRITE	"WALWrite"	"Waiting for a write to a WAL file. Waiting for WAL buffers to be written to disk."
+
+
+#
+# Wait events - Buffer Pin
+#
+
+Section: ClassName - WaitEventBufferPin
+
+WAIT_EVENT_BUFFER_PIN	"BufferPin"	"Waiting to acquire an exclusive pin on a buffer."
+
+
+#
+# Wait events - Extension
+#
+
+Section: ClassName - WaitEventExtension
+
+WAIT_EVENT_EXTENSION	"Extension"	"Waiting in an extension."
+
+#
+# Wait events - LWLock
+#
+# This class of wait events has its own set of C structure, so these are
+# only used for the documentation.
+#
+
+Section: ClassName - WaitEventLWLock
+
+WAIT_EVENT_DOCONLY	"ShmemIndex"	"Waiting to find or allocate space in shared memory."
+WAIT_EVENT_DOCONLY	"OidGen"	"Waiting to allocate a new OID."
+WAIT_EVENT_DOCONLY	"XidGen"	"Waiting to allocate a new transaction ID."
+WAIT_EVENT_DOCONLY	"ProcArray"	"Waiting to access the shared per-process data structures (typically, to get a snapshot or report a session's transaction ID)."
+WAIT_EVENT_DOCONLY	"SInvalRead"	"Waiting to retrieve messages from the shared catalog invalidation queue."
+WAIT_EVENT_DOCONLY	"SInvalWrite"	"Waiting to add a message to the shared catalog invalidation queue."
+WAIT_EVENT_DOCONLY	"WALBufMapping"	"Waiting to replace a page in WAL buffers."
+WAIT_EVENT_DOCONLY	"WALWrite"	"Waiting for WAL buffers to be written to disk."
+WAIT_EVENT_DOCONLY	"ControlFile"	"Waiting to read or update the <filename>pg_control</filename> file or create a new WAL file."
+WAIT_EVENT_DOCONLY	"XactSLRU"	"Waiting to access the transaction status SLRU cache."
+WAIT_EVENT_DOCONLY	"SubtransSLRU"	"Waiting to access the sub-transaction SLRU cache."
+WAIT_EVENT_DOCONLY	"MultiXactGen"	"Waiting to read or update shared multixact state."
+WAIT_EVENT_DOCONLY	"MultiXactOffsetSLRU"	"Waiting to access the multixact offset SLRU cache."
+WAIT_EVENT_DOCONLY	"MultiXactMemberSLRU"	"Waiting to access the multixact member SLRU cache."
+WAIT_EVENT_DOCONLY	"RelCacheInit"	"Waiting to read or update a <filename>pg_internal.init</filename> relation cache initialization file."
+WAIT_EVENT_DOCONLY	"CheckpointerComm"	"Waiting to manage fsync requests."
+WAIT_EVENT_DOCONLY	"TwoPhaseState"	"Waiting to read or update the state of prepared transactions."
+WAIT_EVENT_DOCONLY	"TablespaceCreate"	"Waiting to create or drop a tablespace."
+WAIT_EVENT_DOCONLY	"BtreeVacuum"	"Waiting to read or update vacuum-related information for a B-tree index."
+WAIT_EVENT_DOCONLY	"AddinShmemInit"	"Waiting to manage an extension's space allocation in shared memory."
+WAIT_EVENT_DOCONLY	"Autovacuum"	"Waiting to read or update the current state of autovacuum workers."
+WAIT_EVENT_DOCONLY	"AutovacuumSchedule"	"Waiting to ensure that a table selected for autovacuum still needs vacuuming."
+WAIT_EVENT_DOCONLY	"SyncScan"	"Waiting to select the starting location of a synchronized table scan."
+WAIT_EVENT_DOCONLY	"RelationMapping"	"Waiting to read or update a <filename>pg_filenode.map</filename> file (used to track the filenode assignments of certain system catalogs)."
+WAIT_EVENT_DOCONLY	"NotifySLRU"	"Waiting to access the <command>NOTIFY</command> message SLRU cache."
+WAIT_EVENT_DOCONLY	"NotifyQueue"	"Waiting to read or update <command>NOTIFY</command> messages."
+WAIT_EVENT_DOCONLY	"SerializableXactHash"	"Waiting to read or update information about serializable transactions."
+WAIT_EVENT_DOCONLY	"SerializableFinishedList"	"Waiting to access the list of finished serializable transactions."
+WAIT_EVENT_DOCONLY	"SerializablePredicateList"	"Waiting to access the list of predicate locks held by serializable transactions."
+WAIT_EVENT_DOCONLY	"SerialSLRU"	"Waiting to access the serializable transaction conflict SLRU cache."
+WAIT_EVENT_DOCONLY	"SyncRep"	"Waiting to read or update information about the state of synchronous replication."
+WAIT_EVENT_DOCONLY	"BackgroundWorker"	"Waiting to read or update background worker state."
+WAIT_EVENT_DOCONLY	"DynamicSharedMemoryControl"	"Waiting to read or update dynamic shared memory allocation information."
+WAIT_EVENT_DOCONLY	"AutoFile"	"Waiting to update the <filename>postgresql.auto.conf</filename> file."
+WAIT_EVENT_DOCONLY	"ReplicationSlotAllocation"	"Waiting to allocate or free a replication slot."
+WAIT_EVENT_DOCONLY	"ReplicationSlotControl"	"Waiting to read or update replication slot state."
+WAIT_EVENT_DOCONLY	"CommitTsSLRU"	"Waiting to access the commit timestamp SLRU cache."
+WAIT_EVENT_DOCONLY	"CommitTs"	"Waiting to read or update the last value set for a transaction commit timestamp."
+WAIT_EVENT_DOCONLY	"ReplicationOrigin"	"Waiting to create, drop or use a replication origin."
+WAIT_EVENT_DOCONLY	"MultiXactTruncation"	"Waiting to read or truncate multixact information."
+WAIT_EVENT_DOCONLY	"OldSnapshotTimeMap"	"Waiting to read or update old snapshot control information."
+WAIT_EVENT_DOCONLY	"LogicalRepWorker"	"Waiting to read or update the state of logical replication workers."
+WAIT_EVENT_DOCONLY	"XactTruncation"	"Waiting to execute <function>pg_xact_status</function> or update the oldest transaction ID available to it."
+WAIT_EVENT_DOCONLY	"WrapLimitsVacuum"	"Waiting to update limits on transaction id and multixact consumption."
+WAIT_EVENT_DOCONLY	"NotifyQueueTail"	"Waiting to update limit on <command>NOTIFY</command> message storage."
+
+WAIT_EVENT_DOCONLY	"XactBuffer"	"Waiting for I/O on a transaction status SLRU buffer."
+WAIT_EVENT_DOCONLY	"CommitTsBuffer"	"Waiting for I/O on a commit timestamp SLRU buffer."
+WAIT_EVENT_DOCONLY	"SubtransBuffer"	"Waiting for I/O on a sub-transaction SLRU buffer."
+WAIT_EVENT_DOCONLY	"MultiXactOffsetBuffer"	"Waiting for I/O on a multixact offset SLRU buffer."
+WAIT_EVENT_DOCONLY	"MultiXactMemberBuffer"	"Waiting for I/O on a multixact member SLRU buffer."
+WAIT_EVENT_DOCONLY	"NotifyBuffer"	"Waiting for I/O on a <command>NOTIFY</command> message SLRU buffer."
+WAIT_EVENT_DOCONLY	"SerialBuffer"	"Waiting for I/O on a serializable transaction conflict SLRU buffer."
+WAIT_EVENT_DOCONLY	"WALInsert"	"Waiting to insert WAL data into a memory buffer."
+WAIT_EVENT_DOCONLY	"BufferContent"	"Waiting to access a data page in memory."
+WAIT_EVENT_DOCONLY	"ReplicationOriginState"	"Waiting to read or update the progress of one replication origin."
+WAIT_EVENT_DOCONLY	"ReplicationSlotIO"	"Waiting for I/O on a replication slot."
+WAIT_EVENT_DOCONLY	"LockFastPath"	"Waiting to read or update a process' fast-path lock information."
+WAIT_EVENT_DOCONLY	"BufferMapping"	"Waiting to associate a data block with a buffer in the buffer pool."
+WAIT_EVENT_DOCONLY	"LockManager"	"Waiting to read or update information  about <quote>heavyweight</quote> locks."
+WAIT_EVENT_DOCONLY	"PredicateLockManager"	"Waiting to access predicate lock information used by serializable transactions."
+WAIT_EVENT_DOCONLY	"ParallelHashJoin"	"Waiting to synchronize workers during Parallel Hash Join plan execution."
+WAIT_EVENT_DOCONLY	"ParallelQueryDSA"	"Waiting for parallel query dynamic shared memory allocation."
+WAIT_EVENT_DOCONLY	"PerSessionDSA"	"Waiting for parallel query dynamic shared memory allocation."
+WAIT_EVENT_DOCONLY	"PerSessionRecordType"	"Waiting to access a parallel query's information about composite types."
+WAIT_EVENT_DOCONLY	"PerSessionRecordTypmod"	"Waiting to access a parallel query's information about type modifiers that identify anonymous record types."
+WAIT_EVENT_DOCONLY	"SharedTupleStore"	"Waiting to access a shared tuple store during parallel query."
+WAIT_EVENT_DOCONLY	"SharedTidBitmap"	"Waiting to access a shared TID bitmap during a parallel bitmap index scan."
+WAIT_EVENT_DOCONLY	"ParallelAppend"	"Waiting to choose the next subplan during Parallel Append plan execution."
+WAIT_EVENT_DOCONLY	"PerXactPredicateList"	"Waiting to access the list of predicate locks held by the current serializable transaction during a parallel query."
+WAIT_EVENT_DOCONLY	"PgStatsDSA"	"Waiting for stats dynamic shared memory allocator access."
+WAIT_EVENT_DOCONLY	"PgStatsHash"	"Waiting for stats shared memory hash table access."
+WAIT_EVENT_DOCONLY	"PgStatsData"	"Waiting for shared memory stats data access."
+WAIT_EVENT_DOCONLY	"LogicalRepLauncherDSA"	"Waiting to access logical replication launcher's dynamic shared memory allocator."
+WAIT_EVENT_DOCONLY	"LogicalRepLauncherHash"	"Waiting to access logical replication launcher's shared hash table."
+
+#
+# Wait even - Lock
+#
+# This class of wait events has its own set of C structure, so these are
+# only used for the documentation.
+#
+
+Section: ClassName - WaitEventLock
+
+WAIT_EVENT_DOCONLY	"relation"	"Waiting to acquire a lock on a relation."
+WAIT_EVENT_DOCONLY	"extend"	"Waiting to extend a relation."
+WAIT_EVENT_DOCONLY	"frozenid"	"Waiting to update <structname>pg_database</structname>.<structfield>datfrozenxid</structfield> and <structname>pg_database</structname>.<structfield>datminmxid</structfield>."
+WAIT_EVENT_DOCONLY	"page"	"Waiting to acquire a lock on a page of a relation."
+WAIT_EVENT_DOCONLY	"tuple"	"Waiting to acquire a lock on a tuple."
+WAIT_EVENT_DOCONLY	"transactionid"	"Waiting for a transaction to finish."
+WAIT_EVENT_DOCONLY	"virtualxid"	"Waiting to acquire a virtual transaction ID lock; see <xref linkend="transaction-id"/>."
+WAIT_EVENT_DOCONLY	"spectoken"	"Waiting to acquire a speculative insertion lock."
+WAIT_EVENT_DOCONLY	"object"	"Waiting to acquire a lock on a non-relation database object."
+WAIT_EVENT_DOCONLY	"userlock"	"Waiting to acquire a user lock."
+WAIT_EVENT_DOCONLY	"advisory"	"Waiting to acquire an advisory user lock."
+WAIT_EVENT_DOCONLY	"applytransaction"	"Waiting to acquire a lock on a remote transaction being applied by a logical replication subscriber."
diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c
index f9b9590997..d05e20b2c8 100644
--- a/src/backend/utils/adt/lockfuncs.c
+++ b/src/backend/utils/adt/lockfuncs.c
@@ -24,7 +24,8 @@
 
 /*
  * This must match enum LockTagType!  Also, be sure to document any changes
- * in the docs for the pg_locks view and for wait event types.
+ * in the docs for the pg_locks view and update the WaitEventLOCK section in
+ * src/backend/utils/activity/wait_event_names.txt.
  */
 const char *const LockTagTypeNames[] = {
 	"relation",
diff --git a/src/common/meson.build b/src/common/meson.build
index 9efc80ac02..53942a9a61 100644
--- a/src/common/meson.build
+++ b/src/common/meson.build
@@ -117,13 +117,14 @@ common_sources_frontend_static += files(
 # XXX: in most environments we could probably link_whole pgcommon_shlib
 # against pgcommon_static, instead of compiling twice.
 #
-# For the server build of pgcommon, depend on lwlocknames_h, because at least
-# cryptohash_openssl.c, hmac_openssl.c depend on it. That's arguably a
+# For the server build of pgcommon, depend on lwlocknames_h and because at
+# least cryptohash_openssl.c, hmac_openssl.c depend on it.
+# controldata_utils.c depends on wait_event_types_h. That's arguably a
 # layering violation, but ...
 pgcommon = {}
 pgcommon_variants = {
   '_srv': internal_lib_args + {
-    'sources': common_sources + [lwlocknames_h],
+    'sources': common_sources + [lwlocknames_h] + [wait_event_types_h],
     'dependencies': [backend_common_code],
   },
   '': default_lib_args + {
diff --git a/src/test/ssl/t/002_scram.pl b/src/test/ssl/t/002_scram.pl
index 3a798e1a56..27abd02abf 100644
--- a/src/test/ssl/t/002_scram.pl
+++ b/src/test/ssl/t/002_scram.pl
@@ -87,8 +87,7 @@ $node->connect_fails(
 	expected_stderr => qr/invalid channel_binding value: "invalid_value"/);
 $node->connect_ok("$common_connstr user=ssltestuser channel_binding=disable",
 	"SCRAM with SSL and channel_binding=disable");
-$node->connect_ok(
-	"$common_connstr user=ssltestuser channel_binding=require",
+$node->connect_ok("$common_connstr user=ssltestuser channel_binding=require",
 	"SCRAM with SSL and channel_binding=require");
 
 # Now test when the user has an MD5-encrypted password; should fail
diff --git a/doc/src/sgml/.gitignore b/doc/src/sgml/.gitignore
index d8e3dab338..1ccb72227e 100644
--- a/doc/src/sgml/.gitignore
+++ b/doc/src/sgml/.gitignore
@@ -17,6 +17,7 @@
 /errcodes-table.sgml
 /keywords-table.sgml
 /version.sgml
+/wait_event_types.sgml
 # Assorted byproducts from building the above
 /postgres-full.xml
 /INSTALL.html
diff --git a/doc/src/sgml/Makefile b/doc/src/sgml/Makefile
index 71cbef230f..c4aa6a474f 100644
--- a/doc/src/sgml/Makefile
+++ b/doc/src/sgml/Makefile
@@ -58,7 +58,7 @@ override XSLTPROCFLAGS += --stringparam pg.version '$(VERSION)'
 
 GENERATED_SGML = version.sgml \
 	features-supported.sgml features-unsupported.sgml errcodes-table.sgml \
-	keywords-table.sgml
+	keywords-table.sgml wait_event_types.sgml
 
 ALLSGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML)
 
@@ -111,6 +111,9 @@ errcodes-table.sgml: $(top_srcdir)/src/backend/utils/errcodes.txt generate-errco
 keywords-table.sgml: $(top_srcdir)/src/include/parser/kwlist.h $(wildcard $(srcdir)/keywords/sql*.txt) generate-keywords-table.pl
 	$(PERL) $(srcdir)/generate-keywords-table.pl $(srcdir) > $@
 
+wait_event_types.sgml: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl
+	$(PERL) $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl $< > $@
+	rm pgstat_wait_event.c; rm wait_event_types.h
 
 ##
 ## Generation of some text files.
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 5465f9a46d..63b0fc2a46 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -42,6 +42,7 @@
 <!ENTITY maintenance   SYSTEM "maintenance.sgml">
 <!ENTITY manage-ag     SYSTEM "manage-ag.sgml">
 <!ENTITY monitoring    SYSTEM "monitoring.sgml">
+<!ENTITY wait_event_types    SYSTEM "wait_event_types.sgml">
 <!ENTITY regress       SYSTEM "regress.sgml">
 <!ENTITY runtime       SYSTEM "runtime.sgml">
 <!ENTITY config        SYSTEM "config.sgml">
diff --git a/doc/src/sgml/meson.build b/doc/src/sgml/meson.build
index c6d77b5a15..c2cc97d408 100644
--- a/doc/src/sgml/meson.build
+++ b/doc/src/sgml/meson.build
@@ -46,6 +46,18 @@ doc_generated += custom_target('errcodes-table.sgml',
   capture: true,
 )
 
+doc_generated += custom_target('wait_event_types.sgml',
+  input: files(
+    '../../../src/backend/utils/activity/wait_event_names.txt'),
+  output: 'wait_event_types.sgml',
+  command: [perl,
+    files('../../../src/backend/utils/activity/generate-wait_event_types.pl'),
+    '--outdir', '@OUTDIR@', '@INPUT@'],
+  build_by_default: false,
+  install: false,
+  capture: true,
+)
+
 # FIXME: this actually has further inputs, adding depfile support to
 # generate-keywords-table.pl is probably the best way to address that
 # robustly.
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 5cfdc70c03..506aeaa879 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -1100,1266 +1100,7 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
    </tgroup>
   </table>
 
-  <table id="wait-event-activity-table">
-   <title>Wait Events of Type <literal>Activity</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Activity</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>ArchiverMain</literal></entry>
-      <entry>Waiting in main loop of archiver process.</entry>
-     </row>
-     <row>
-      <entry><literal>AutoVacuumMain</literal></entry>
-      <entry>Waiting in main loop of autovacuum launcher process.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWriterHibernate</literal></entry>
-      <entry>Waiting in background writer process, hibernating.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWriterMain</literal></entry>
-      <entry>Waiting in main loop of background writer process.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointerMain</literal></entry>
-      <entry>Waiting in main loop of checkpointer process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalApplyMain</literal></entry>
-      <entry>Waiting in main loop of logical replication apply process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalLauncherMain</literal></entry>
-      <entry>Waiting in main loop of logical replication launcher process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalParallelApplyMain</literal></entry>
-      <entry>Waiting in main loop of logical replication parallel apply
-       process.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryWalStream</literal></entry>
-      <entry>Waiting in main loop of startup process for WAL to arrive, during
-       streaming recovery.</entry>
-     </row>
-     <row>
-      <entry><literal>SysLoggerMain</literal></entry>
-      <entry>Waiting in main loop of syslogger process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalReceiverMain</literal></entry>
-      <entry>Waiting in main loop of WAL receiver process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalSenderMain</literal></entry>
-      <entry>Waiting in main loop of WAL sender process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalWriterMain</literal></entry>
-      <entry>Waiting in main loop of WAL writer process.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-bufferpin-table">
-   <title>Wait Events of Type <literal>BufferPin</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>BufferPin</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>BufferPin</literal></entry>
-      <entry>Waiting to acquire an exclusive pin on a buffer.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-client-table">
-   <title>Wait Events of Type <literal>Client</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Client</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>ClientRead</literal></entry>
-      <entry>Waiting to read data from the client.</entry>
-     </row>
-     <row>
-      <entry><literal>ClientWrite</literal></entry>
-      <entry>Waiting to write data to the client.</entry>
-     </row>
-     <row>
-      <entry><literal>GSSOpenServer</literal></entry>
-      <entry>Waiting to read data from the client while establishing a GSSAPI
-       session.</entry>
-     </row>
-     <row>
-      <entry><literal>LibPQWalReceiverConnect</literal></entry>
-      <entry>Waiting in WAL receiver to establish connection to remote
-       server.</entry>
-     </row>
-     <row>
-      <entry><literal>LibPQWalReceiverReceive</literal></entry>
-      <entry>Waiting in WAL receiver to receive data from remote server.</entry>
-     </row>
-     <row>
-      <entry><literal>SSLOpenServer</literal></entry>
-      <entry>Waiting for SSL while attempting connection.</entry>
-     </row>
-     <row>
-      <entry><literal>WalSenderWaitForWAL</literal></entry>
-      <entry>Waiting for WAL to be flushed in WAL sender process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalSenderWriteData</literal></entry>
-      <entry>Waiting for any activity when processing replies from WAL
-       receiver in WAL sender process.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-extension-table">
-   <title>Wait Events of Type <literal>Extension</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Extension</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>Extension</literal></entry>
-      <entry>Waiting in an extension.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-io-table">
-   <title>Wait Events of Type <literal>IO</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>IO</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>BaseBackupRead</literal></entry>
-      <entry>Waiting for base backup to read from a file.</entry>
-     </row>
-     <row>
-      <entry><literal>BaseBackupSync</literal></entry>
-      <entry>Waiting for data written by a base backup to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>BaseBackupWrite</literal></entry>
-      <entry>Waiting for base backup to write to a file.</entry>
-     </row>
-     <row>
-      <entry><literal>BufFileRead</literal></entry>
-      <entry>Waiting for a read from a buffered file.</entry>
-     </row>
-     <row>
-      <entry><literal>BufFileTruncate</literal></entry>
-      <entry>Waiting for a buffered file to be truncated.</entry>
-     </row>
-     <row>
-      <entry><literal>BufFileWrite</literal></entry>
-      <entry>Waiting for a write to a buffered file.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileRead</literal></entry>
-      <entry>Waiting for a read from the <filename>pg_control</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileSync</literal></entry>
-      <entry>Waiting for the <filename>pg_control</filename> file to reach
-       durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileSyncUpdate</literal></entry>
-      <entry>Waiting for an update to the <filename>pg_control</filename> file
-       to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileWrite</literal></entry>
-      <entry>Waiting for a write to the <filename>pg_control</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileWriteUpdate</literal></entry>
-      <entry>Waiting for a write to update the <filename>pg_control</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>CopyFileRead</literal></entry>
-      <entry>Waiting for a read during a file copy operation.</entry>
-     </row>
-     <row>
-      <entry><literal>CopyFileWrite</literal></entry>
-      <entry>Waiting for a write during a file copy operation.</entry>
-     </row>
-     <row>
-      <entry><literal>DSMAllocate</literal></entry>
-      <entry>Waiting for a dynamic shared memory segment to be
-       allocated.</entry>
-     </row>
-     <row>
-      <entry><literal>DSMFillZeroWrite</literal></entry>
-      <entry>Waiting to fill a dynamic shared memory backing file with
-       zeroes.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileExtend</literal></entry>
-      <entry>Waiting for a relation data file to be extended.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileFlush</literal></entry>
-      <entry>Waiting for a relation data file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileImmediateSync</literal></entry>
-      <entry>Waiting for an immediate synchronization of a relation data file to
-       durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFilePrefetch</literal></entry>
-      <entry>Waiting for an asynchronous prefetch from a relation data
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileRead</literal></entry>
-      <entry>Waiting for a read from a relation data file.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileSync</literal></entry>
-      <entry>Waiting for changes to a relation data file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileTruncate</literal></entry>
-      <entry>Waiting for a relation data file to be truncated.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileWrite</literal></entry>
-      <entry>Waiting for a write to a relation data file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileAddToDataDirRead</literal></entry>
-      <entry>Waiting for a read while adding a line to the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileAddToDataDirSync</literal></entry>
-      <entry>Waiting for data to reach durable storage while adding a line to the
-       data directory lock file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileAddToDataDirWrite</literal></entry>
-      <entry>Waiting for a write while adding a line to the data directory
-       lock file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileCreateRead</literal></entry>
-      <entry>Waiting to read while creating the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileCreateSync</literal></entry>
-      <entry>Waiting for data to reach durable storage while creating the data
-       directory lock file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileCreateWrite</literal></entry>
-      <entry>Waiting for a write while creating the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileReCheckDataDirRead</literal></entry>
-      <entry>Waiting for a read during recheck of the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteCheckpointSync</literal></entry>
-      <entry>Waiting for logical rewrite mappings to reach durable storage
-       during a checkpoint.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteMappingSync</literal></entry>
-      <entry>Waiting for mapping data to reach durable storage during a logical
-       rewrite.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteMappingWrite</literal></entry>
-      <entry>Waiting for a write of mapping data during a logical
-       rewrite.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteSync</literal></entry>
-      <entry>Waiting for logical rewrite mappings to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteTruncate</literal></entry>
-      <entry>Waiting for truncate of mapping data during a logical
-       rewrite.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteWrite</literal></entry>
-      <entry>Waiting for a write of logical rewrite mappings.</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapRead</literal></entry>
-      <entry>Waiting for a read of the relation map file.</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapReplace</literal></entry>
-      <entry>Waiting for durable replacement of a relation map file.</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapWrite</literal></entry>
-      <entry>Waiting for a write to the relation map file.</entry>
-     </row>
-     <row>
-      <entry><literal>ReorderBufferRead</literal></entry>
-      <entry>Waiting for a read during reorder buffer management.</entry>
-     </row>
-     <row>
-      <entry><literal>ReorderBufferWrite</literal></entry>
-      <entry>Waiting for a write during reorder buffer management.</entry>
-     </row>
-     <row>
-      <entry><literal>ReorderLogicalMappingRead</literal></entry>
-      <entry>Waiting for a read of a logical mapping during reorder buffer
-       management.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotRead</literal></entry>
-      <entry>Waiting for a read from a replication slot control file.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotRestoreSync</literal></entry>
-      <entry>Waiting for a replication slot control file to reach durable storage
-       while restoring it to memory.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotSync</literal></entry>
-      <entry>Waiting for a replication slot control file to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotWrite</literal></entry>
-      <entry>Waiting for a write to a replication slot control file.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRUFlushSync</literal></entry>
-      <entry>Waiting for SLRU data to reach durable storage during a checkpoint
-       or database shutdown.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRURead</literal></entry>
-      <entry>Waiting for a read of an SLRU page.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRUSync</literal></entry>
-      <entry>Waiting for SLRU data to reach durable storage following a page
-       write.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRUWrite</literal></entry>
-      <entry>Waiting for a write of an SLRU page.</entry>
-     </row>
-     <row>
-      <entry><literal>SnapbuildRead</literal></entry>
-      <entry>Waiting for a read of a serialized historical catalog
-       snapshot.</entry>
-     </row>
-     <row>
-      <entry><literal>SnapbuildSync</literal></entry>
-      <entry>Waiting for a serialized historical catalog snapshot to reach
-       durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>SnapbuildWrite</literal></entry>
-      <entry>Waiting for a write of a serialized historical catalog
-       snapshot.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryFileSync</literal></entry>
-      <entry>Waiting for a timeline history file received via streaming
-       replication to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryFileWrite</literal></entry>
-      <entry>Waiting for a write of a timeline history file received via
-       streaming replication.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryRead</literal></entry>
-      <entry>Waiting for a read of a timeline history file.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistorySync</literal></entry>
-      <entry>Waiting for a newly created timeline history file to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryWrite</literal></entry>
-      <entry>Waiting for a write of a newly created timeline history
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>TwophaseFileRead</literal></entry>
-      <entry>Waiting for a read of a two phase state file.</entry>
-     </row>
-     <row>
-      <entry><literal>TwophaseFileSync</literal></entry>
-      <entry>Waiting for a two phase state file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>TwophaseFileWrite</literal></entry>
-      <entry>Waiting for a write of a two phase state file.</entry>
-     </row>
-     <row>
-      <entry><literal>VersionFileWrite</literal></entry>
-      <entry>Waiting for the version file to be written while creating a database.</entry>
-     </row>
-     <row>
-      <entry><literal>WALBootstrapSync</literal></entry>
-      <entry>Waiting for WAL to reach durable storage during
-       bootstrapping.</entry>
-     </row>
-     <row>
-      <entry><literal>WALBootstrapWrite</literal></entry>
-      <entry>Waiting for a write of a WAL page during bootstrapping.</entry>
-     </row>
-     <row>
-      <entry><literal>WALCopyRead</literal></entry>
-      <entry>Waiting for a read when creating a new WAL segment by copying an
-       existing one.</entry>
-     </row>
-     <row>
-      <entry><literal>WALCopySync</literal></entry>
-      <entry>Waiting for a new WAL segment created by copying an existing one to
-       reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>WALCopyWrite</literal></entry>
-      <entry>Waiting for a write when creating a new WAL segment by copying an
-       existing one.</entry>
-     </row>
-     <row>
-      <entry><literal>WALInitSync</literal></entry>
-      <entry>Waiting for a newly initialized WAL file to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>WALInitWrite</literal></entry>
-      <entry>Waiting for a write while initializing a new WAL file.</entry>
-     </row>
-     <row>
-      <entry><literal>WALRead</literal></entry>
-      <entry>Waiting for a read from a WAL file.</entry>
-     </row>
-     <row>
-      <entry><literal>WALSenderTimelineHistoryRead</literal></entry>
-      <entry>Waiting for a read from a timeline history file during a walsender
-       timeline command.</entry>
-     </row>
-     <row>
-      <entry><literal>WALSync</literal></entry>
-      <entry>Waiting for a WAL file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>WALSyncMethodAssign</literal></entry>
-      <entry>Waiting for data to reach durable storage while assigning a new
-       WAL sync method.</entry>
-     </row>
-     <row>
-      <entry><literal>WALWrite</literal></entry>
-      <entry>Waiting for a write to a WAL file.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-ipc-table">
-   <title>Wait Events of Type <literal>IPC</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>IPC</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>AppendReady</literal></entry>
-      <entry>Waiting for subplan nodes of an <literal>Append</literal> plan
-       node to be ready.</entry>
-     </row>
-     <row>
-      <entry><literal>ArchiveCleanupCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-archive-cleanup-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>ArchiveCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-archive-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>BackendTermination</literal></entry>
-      <entry>Waiting for the termination of another backend.</entry>
-     </row>
-     <row>
-      <entry><literal>BackupWaitWalArchive</literal></entry>
-      <entry>Waiting for WAL files required for a backup to be successfully
-       archived.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWorkerShutdown</literal></entry>
-      <entry>Waiting for background worker to shut down.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWorkerStartup</literal></entry>
-      <entry>Waiting for background worker to start up.</entry>
-     </row>
-     <row>
-      <entry><literal>BtreePage</literal></entry>
-      <entry>Waiting for the page number needed to continue a parallel B-tree
-       scan to become available.</entry>
-     </row>
-     <row>
-      <entry><literal>BufferIO</literal></entry>
-      <entry>Waiting for buffer I/O to complete.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointDone</literal></entry>
-      <entry>Waiting for a checkpoint to complete.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointStart</literal></entry>
-      <entry>Waiting for a checkpoint to start.</entry>
-     </row>
-     <row>
-      <entry><literal>ExecuteGather</literal></entry>
-      <entry>Waiting for activity from a child process while
-       executing a <literal>Gather</literal> plan node.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBatchAllocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to allocate a hash
-       table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBatchElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate a hash
-       table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBatchLoad</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish loading a
-       hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildAllocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to allocate the
-       initial hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate the
-       initial hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildHashInner</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish hashing the
-       inner relation.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildHashOuter</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish partitioning
-       the outer relation.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesDecide</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to decide on future
-       batch growth.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate more
-       batches.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesFinish</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to decide on
-       future batch growth.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesReallocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to allocate more
-       batches.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesRepartition</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish
-       repartitioning.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBucketsElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate more
-       buckets.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBucketsReallocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to finish
-       allocating more buckets.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBucketsReinsert</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish inserting
-       tuples into new buckets.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalApplySendData</literal></entry>
-      <entry>Waiting for a logical replication leader apply process to send
-       data to a parallel apply process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalParallelApplyStateChange</literal></entry>
-      <entry>Waiting for a logical replication parallel apply process to change
-       state.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalSyncData</literal></entry>
-      <entry>Waiting for a logical replication remote server to send data for
-       initial table synchronization.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalSyncStateChange</literal></entry>
-      <entry>Waiting for a logical replication remote server to change
-       state.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueueInternal</literal></entry>
-      <entry>Waiting for another process to be attached to a shared message
-       queue.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueuePutMessage</literal></entry>
-      <entry>Waiting to write a protocol message to a shared message queue.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueueReceive</literal></entry>
-      <entry>Waiting to receive bytes from a shared message queue.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueueSend</literal></entry>
-      <entry>Waiting to send bytes to a shared message queue.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelBitmapScan</literal></entry>
-      <entry>Waiting for parallel bitmap scan to become initialized.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelCreateIndexScan</literal></entry>
-      <entry>Waiting for parallel <command>CREATE INDEX</command> workers to
-       finish heap scan.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelFinish</literal></entry>
-      <entry>Waiting for parallel workers to finish computing.</entry>
-     </row>
-     <row>
-      <entry><literal>ProcArrayGroupUpdate</literal></entry>
-      <entry>Waiting for the group leader to clear the transaction ID at
-       end of a parallel operation.</entry>
-     </row>
-     <row>
-      <entry><literal>ProcSignalBarrier</literal></entry>
-      <entry>Waiting for a barrier event to be processed by all
-       backends.</entry>
-     </row>
-     <row>
-      <entry><literal>Promote</literal></entry>
-      <entry>Waiting for standby promotion.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryConflictSnapshot</literal></entry>
-      <entry>Waiting for recovery conflict resolution for a vacuum
-       cleanup.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryConflictTablespace</literal></entry>
-      <entry>Waiting for recovery conflict resolution for dropping a
-       tablespace.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryEndCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-recovery-end-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryPause</literal></entry>
-      <entry>Waiting for recovery to be resumed.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationOriginDrop</literal></entry>
-      <entry>Waiting for a replication origin to become inactive so it can be
-       dropped.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotDrop</literal></entry>
-      <entry>Waiting for a replication slot to become inactive so it can be
-       dropped.</entry>
-     </row>
-     <row>
-      <entry><literal>RestoreCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-restore-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>SafeSnapshot</literal></entry>
-      <entry>Waiting to obtain a valid snapshot for a <literal>READ ONLY
-       DEFERRABLE</literal> transaction.</entry>
-     </row>
-     <row>
-      <entry><literal>SyncRep</literal></entry>
-      <entry>Waiting for confirmation from a remote server during synchronous
-       replication.</entry>
-     </row>
-     <row>
-      <entry><literal>WalReceiverExit</literal></entry>
-      <entry>Waiting for the WAL receiver to exit.</entry>
-     </row>
-     <row>
-      <entry><literal>WalReceiverWaitStart</literal></entry>
-      <entry>Waiting for startup process to send initial data for streaming
-       replication.</entry>
-     </row>
-     <row>
-      <entry><literal>XactGroupUpdate</literal></entry>
-      <entry>Waiting for the group leader to update transaction status at
-       end of a parallel operation.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-lock-table">
-   <title>Wait Events of Type <literal>Lock</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Lock</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>advisory</literal></entry>
-      <entry>Waiting to acquire an advisory user lock.</entry>
-     </row>
-     <row>
-      <entry><literal>applytransaction</literal></entry>
-      <entry>Waiting to acquire a lock on a remote transaction being applied
-      by a logical replication subscriber.</entry>
-     </row>
-     <row>
-      <entry><literal>extend</literal></entry>
-      <entry>Waiting to extend a relation.</entry>
-     </row>
-     <row>
-      <entry><literal>frozenid</literal></entry>
-      <entry>Waiting to
-       update <structname>pg_database</structname>.<structfield>datfrozenxid</structfield>
-       and <structname>pg_database</structname>.<structfield>datminmxid</structfield>.</entry>
-     </row>
-     <row>
-      <entry><literal>object</literal></entry>
-      <entry>Waiting to acquire a lock on a non-relation database object.</entry>
-     </row>
-     <row>
-      <entry><literal>page</literal></entry>
-      <entry>Waiting to acquire a lock on a page of a relation.</entry>
-     </row>
-     <row>
-      <entry><literal>relation</literal></entry>
-      <entry>Waiting to acquire a lock on a relation.</entry>
-     </row>
-     <row>
-      <entry><literal>spectoken</literal></entry>
-      <entry>Waiting to acquire a speculative insertion lock.</entry>
-     </row>
-     <row>
-      <entry><literal>transactionid</literal></entry>
-      <entry>Waiting for a transaction to finish.</entry>
-     </row>
-     <row>
-      <entry><literal>tuple</literal></entry>
-      <entry>Waiting to acquire a lock on a tuple.</entry>
-     </row>
-     <row>
-      <entry><literal>userlock</literal></entry>
-      <entry>Waiting to acquire a user lock.</entry>
-     </row>
-     <row>
-      <entry><literal>virtualxid</literal></entry>
-      <entry>Waiting to acquire a virtual transaction ID lock;  see
-      <xref linkend="transaction-id"/>.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-lwlock-table">
-   <title>Wait Events of Type <literal>LWLock</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>LWLock</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>AddinShmemInit</literal></entry>
-      <entry>Waiting to manage an extension's space allocation in shared
-       memory.</entry>
-     </row>
-     <row>
-      <entry><literal>AutoFile</literal></entry>
-      <entry>Waiting to update the <filename>postgresql.auto.conf</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>Autovacuum</literal></entry>
-      <entry>Waiting to read or update the current state of autovacuum
-       workers.</entry>
-     </row>
-     <row>
-      <entry><literal>AutovacuumSchedule</literal></entry>
-      <entry>Waiting to ensure that a table selected for autovacuum
-       still needs vacuuming.</entry>
-     </row>
-     <row>
-      <entry><literal>BackgroundWorker</literal></entry>
-      <entry>Waiting to read or update background worker state.</entry>
-     </row>
-     <row>
-      <entry><literal>BtreeVacuum</literal></entry>
-      <entry>Waiting to read or update vacuum-related information for a
-       B-tree index.</entry>
-     </row>
-     <row>
-      <entry><literal>BufferContent</literal></entry>
-      <entry>Waiting to access a data page in memory.</entry>
-     </row>
-     <row>
-      <entry><literal>BufferMapping</literal></entry>
-      <entry>Waiting to associate a data block with a buffer in the buffer
-       pool.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointerComm</literal></entry>
-      <entry>Waiting to manage fsync requests.</entry>
-     </row>
-     <row>
-      <entry><literal>CommitTs</literal></entry>
-      <entry>Waiting to read or update the last value set for a
-       transaction commit timestamp.</entry>
-     </row>
-     <row>
-      <entry><literal>CommitTsBuffer</literal></entry>
-      <entry>Waiting for I/O on a commit timestamp SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>CommitTsSLRU</literal></entry>
-      <entry>Waiting to access the commit timestamp SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFile</literal></entry>
-      <entry>Waiting to read or update the <filename>pg_control</filename>
-       file or create a new WAL file.</entry>
-     </row>
-     <row>
-      <entry><literal>DynamicSharedMemoryControl</literal></entry>
-      <entry>Waiting to read or update dynamic shared memory allocation
-       information.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFastPath</literal></entry>
-      <entry>Waiting to read or update a process' fast-path lock
-       information.</entry>
-     </row>
-     <row>
-      <entry><literal>LockManager</literal></entry>
-      <entry>Waiting to read or update information
-       about <quote>heavyweight</quote> locks.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRepLauncherDSA</literal></entry>
-      <entry>Waiting to access logical replication launcher's dynamic shared
-       memory allocator.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRepLauncherHash</literal></entry>
-      <entry>Waiting to access logical replication launcher's shared
-       hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRepWorker</literal></entry>
-      <entry>Waiting to read or update the state of logical replication
-       workers.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactGen</literal></entry>
-      <entry>Waiting to read or update shared multixact state.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactMemberBuffer</literal></entry>
-      <entry>Waiting for I/O on a multixact member SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactMemberSLRU</literal></entry>
-      <entry>Waiting to access the multixact member SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactOffsetBuffer</literal></entry>
-      <entry>Waiting for I/O on a multixact offset SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactOffsetSLRU</literal></entry>
-      <entry>Waiting to access the multixact offset SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactTruncation</literal></entry>
-      <entry>Waiting to read or truncate multixact information.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifyBuffer</literal></entry>
-      <entry>Waiting for I/O on a <command>NOTIFY</command> message SLRU
-       buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifyQueue</literal></entry>
-      <entry>Waiting to read or update <command>NOTIFY</command> messages.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifyQueueTail</literal></entry>
-      <entry>Waiting to update limit on <command>NOTIFY</command> message
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifySLRU</literal></entry>
-      <entry>Waiting to access the <command>NOTIFY</command> message SLRU
-       cache.</entry>
-     </row>
-     <row>
-      <entry><literal>OidGen</literal></entry>
-      <entry>Waiting to allocate a new OID.</entry>
-     </row>
-     <row>
-      <entry><literal>OldSnapshotTimeMap</literal></entry>
-      <entry>Waiting to read or update old snapshot control information.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelAppend</literal></entry>
-      <entry>Waiting to choose the next subplan during Parallel Append plan
-       execution.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelHashJoin</literal></entry>
-      <entry>Waiting to synchronize workers during Parallel Hash Join plan
-       execution.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelQueryDSA</literal></entry>
-      <entry>Waiting for parallel query dynamic shared memory allocation.</entry>
-     </row>
-     <row>
-      <entry><literal>PerSessionDSA</literal></entry>
-      <entry>Waiting for parallel query dynamic shared memory allocation.</entry>
-     </row>
-     <row>
-      <entry><literal>PerSessionRecordType</literal></entry>
-      <entry>Waiting to access a parallel query's information about composite
-       types.</entry>
-     </row>
-     <row>
-      <entry><literal>PerSessionRecordTypmod</literal></entry>
-      <entry>Waiting to access a parallel query's information about type
-       modifiers that identify anonymous record types.</entry>
-     </row>
-     <row>
-      <entry><literal>PerXactPredicateList</literal></entry>
-      <entry>Waiting to access the list of predicate locks held by the current
-       serializable transaction during a parallel query.</entry>
-     </row>
-     <row>
-      <entry><literal>PgStatsData</literal></entry>
-      <entry>Waiting for shared memory stats data access</entry>
-     </row>
-     <row>
-      <entry><literal>PgStatsDSA</literal></entry>
-      <entry>Waiting for stats dynamic shared memory allocator access</entry>
-     </row>
-     <row>
-      <entry><literal>PgStatsHash</literal></entry>
-      <entry>Waiting for stats shared memory hash table access</entry>
-     </row>
-     <row>
-      <entry><literal>PredicateLockManager</literal></entry>
-      <entry>Waiting to access predicate lock information used by
-       serializable transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>ProcArray</literal></entry>
-      <entry>Waiting to access the shared per-process data structures
-       (typically, to get a snapshot or report a session's transaction
-       ID).</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapping</literal></entry>
-      <entry>Waiting to read or update
-       a <filename>pg_filenode.map</filename> file (used to track the
-       filenode assignments of certain system catalogs).</entry>
-     </row>
-     <row>
-      <entry><literal>RelCacheInit</literal></entry>
-      <entry>Waiting to read or update a <filename>pg_internal.init</filename>
-       relation cache initialization file.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationOrigin</literal></entry>
-      <entry>Waiting to create, drop or use a replication origin.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationOriginState</literal></entry>
-      <entry>Waiting to read or update the progress of one replication
-       origin.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotAllocation</literal></entry>
-      <entry>Waiting to allocate or free a replication slot.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotControl</literal></entry>
-      <entry>Waiting to read or update replication slot state.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotIO</literal></entry>
-      <entry>Waiting for I/O on a replication slot.</entry>
-     </row>
-     <row>
-      <entry><literal>SerialBuffer</literal></entry>
-      <entry>Waiting for I/O on a serializable transaction conflict SLRU
-       buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>SerializableFinishedList</literal></entry>
-      <entry>Waiting to access the list of finished serializable
-       transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>SerializablePredicateList</literal></entry>
-      <entry>Waiting to access the list of predicate locks held by
-       serializable transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>SerializableXactHash</literal></entry>
-      <entry>Waiting to read or update information about serializable
-       transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>SerialSLRU</literal></entry>
-      <entry>Waiting to access the serializable transaction conflict SLRU
-       cache.</entry>
-     </row>
-     <row>
-      <entry><literal>SharedTidBitmap</literal></entry>
-      <entry>Waiting to access a shared TID bitmap during a parallel bitmap
-       index scan.</entry>
-     </row>
-     <row>
-      <entry><literal>SharedTupleStore</literal></entry>
-      <entry>Waiting to access a shared tuple store during parallel
-       query.</entry>
-     </row>
-     <row>
-      <entry><literal>ShmemIndex</literal></entry>
-      <entry>Waiting to find or allocate space in shared memory.</entry>
-     </row>
-     <row>
-      <entry><literal>SInvalRead</literal></entry>
-      <entry>Waiting to retrieve messages from the shared catalog invalidation
-       queue.</entry>
-     </row>
-     <row>
-      <entry><literal>SInvalWrite</literal></entry>
-      <entry>Waiting to add a message to the shared catalog invalidation
-      queue.</entry>
-     </row>
-     <row>
-      <entry><literal>SubtransBuffer</literal></entry>
-      <entry>Waiting for I/O on a sub-transaction SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>SubtransSLRU</literal></entry>
-      <entry>Waiting to access the sub-transaction SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>SyncRep</literal></entry>
-      <entry>Waiting to read or update information about the state of
-       synchronous replication.</entry>
-     </row>
-     <row>
-      <entry><literal>SyncScan</literal></entry>
-      <entry>Waiting to select the starting location of a synchronized table
-       scan.</entry>
-     </row>
-     <row>
-      <entry><literal>TablespaceCreate</literal></entry>
-      <entry>Waiting to create or drop a tablespace.</entry>
-     </row>
-     <row>
-      <entry><literal>TwoPhaseState</literal></entry>
-      <entry>Waiting to read or update the state of prepared transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>WALBufMapping</literal></entry>
-      <entry>Waiting to replace a page in WAL buffers.</entry>
-     </row>
-     <row>
-      <entry><literal>WALInsert</literal></entry>
-      <entry>Waiting to insert WAL data into a memory buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>WALWrite</literal></entry>
-      <entry>Waiting for WAL buffers to be written to disk.</entry>
-     </row>
-     <row>
-      <entry><literal>WrapLimitsVacuum</literal></entry>
-      <entry>Waiting to update limits on transaction id and multixact
-       consumption.</entry>
-     </row>
-     <row>
-      <entry><literal>XactBuffer</literal></entry>
-      <entry>Waiting for I/O on a transaction status SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>XactSLRU</literal></entry>
-      <entry>Waiting to access the transaction status SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>XactTruncation</literal></entry>
-      <entry>Waiting to execute <function>pg_xact_status</function> or update
-       the oldest transaction ID available to it.</entry>
-     </row>
-     <row>
-      <entry><literal>XidGen</literal></entry>
-      <entry>Waiting to allocate a new transaction ID.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-   <note>
-    <para>
-     Extensions can add <literal>LWLock</literal> types to the list shown in
-     <xref linkend="wait-event-lwlock-table"/>.  In some cases, the name
-     assigned by an extension will not be available in all server processes;
-     so an <literal>LWLock</literal> wait event might be reported as
-     just <quote><literal>extension</literal></quote> rather than the
-     extension-assigned name.
-    </para>
-   </note>
-
-  <table id="wait-event-timeout-table">
-   <title>Wait Events of Type <literal>Timeout</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Timeout</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>BaseBackupThrottle</literal></entry>
-      <entry>Waiting during base backup when throttling activity.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointWriteDelay</literal></entry>
-      <entry>Waiting between writes while performing a checkpoint.</entry>
-     </row>
-     <row>
-      <entry><literal>PgSleep</literal></entry>
-      <entry>Waiting due to a call to <function>pg_sleep</function> or
-       a sibling function.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryApplyDelay</literal></entry>
-      <entry>Waiting to apply WAL during recovery because of a delay
-       setting.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryRetrieveRetryInterval</literal></entry>
-      <entry>Waiting during recovery when WAL data is not available from any
-       source (<filename>pg_wal</filename>, archive or stream).</entry>
-     </row>
-     <row>
-      <entry><literal>RegisterSyncRequest</literal></entry>
-      <entry>Waiting while sending synchronization requests to the
-       checkpointer, because the request queue is full.</entry>
-     </row>
-     <row>
-      <entry><literal>SpinDelay</literal></entry>
-      <entry>Waiting while acquiring a contended spinlock.</entry>
-     </row>
-     <row>
-      <entry><literal>VacuumDelay</literal></entry>
-      <entry>Waiting in a cost-based vacuum delay point.</entry>
-     </row>
-     <row>
-      <entry><literal>VacuumTruncate</literal></entry>
-      <entry>Waiting to acquire an exclusive lock to truncate off any
-       empty pages at the end of a table vacuumed.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
+  &wait_event_types;
 
    <para>
      Here is an example of how wait events can be viewed:
@@ -2374,6 +1115,16 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 </programlisting>
    </para>
 
+   <note>
+    <para>
+     Extensions can add <literal>LWLock</literal> types to the list shown in
+     <xref linkend="wait-event-lwlock-table"/>.  In some cases, the name
+     assigned by an extension will not be available in all server processes;
+     so an <literal>LWLock</literal> wait event might be reported as
+     just <quote><literal>extension</literal></quote> rather than the
+     extension-assigned name.
+    </para>
+   </note>
  </sect2>
 
  <sect2 id="monitoring-pg-stat-replication-view">
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index e6d8f9fedc..f6570db479 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -585,6 +585,25 @@ sub GenerateFiles
 			'src/include/storage/lwlocknames.h');
 	}
 
+	if (IsNewer(
+			'src/include/utils/wait_event_types.h',
+			'src/backend/utils/activity/wait_event_names.txt'))
+	{
+		print "Generating pgstat_wait_event.c and wait_event_types.h...\n";
+		my $activ = 'src/backend/utils/activity';
+		system(
+			"perl $activ/generate-wait_event_types.pl --outdir $activ $activ/wait_event_names.txt"
+		);
+	}
+	if (IsNewer(
+			'src/include/utils/wait_event_types.h',
+			'src/backend/utils/activity/wait_event_types.h'))
+	{
+		copyFile(
+			'src/backend/utils/activity/wait_event_types.h',
+			'src/include/utils/wait_event_types.h');
+	}
+
 	if (IsNewer('src/include/utils/probes.h', 'src/backend/utils/probes.d'))
 	{
 		print "Generating probes.h...\n";
diff --git a/src/tools/msvc/clean.bat b/src/tools/msvc/clean.bat
index cf35764604..7cb23ea894 100755
--- a/src/tools/msvc/clean.bat
+++ b/src/tools/msvc/clean.bat
@@ -46,6 +46,7 @@ if exist src\include\utils\errcodes.h del /q src\include\utils\errcodes.h
 if exist src\include\utils\fmgroids.h del /q src\include\utils\fmgroids.h
 if exist src\include\utils\fmgrprotos.h del /q src\include\utils\fmgrprotos.h
 if exist src\include\storage\lwlocknames.h del /q src\include\storage\lwlocknames.h
+if exist src\include\utils\wait_event_types.h del /q src\include\utils\wait_event_types.h
 if exist src\include\utils\probes.h del /q src\include\utils\probes.h
 if exist src\include\catalog\schemapg.h del /q src\include\catalog\schemapg.h
 if exist src\include\catalog\system_fk_info.h del /q src\include\catalog\system_fk_info.h
@@ -53,6 +54,8 @@ if exist src\include\catalog\pg_*_d.h del /q src\include\catalog\pg_*_d.h
 if exist src\include\catalog\header-stamp del /q src\include\catalog\header-stamp
 if exist doc\src\sgml\version.sgml del /q doc\src\sgml\version.sgml
 
+if %DIST%==1 if exist src\backend\utils\activity\pgstat_wait_event.c del /q src\backend\utils\activity\pgstat_wait_event.c
+if %DIST%==1 if exist src\backend\utils\activity\wait_event_types.h del /q src\backend\utils\activity\wait_event_types.h
 if %DIST%==1 if exist src\backend\utils\fmgroids.h del /q src\backend\utils\fmgroids.h
 if %DIST%==1 if exist src\backend\utils\fmgrprotos.h del /q src\backend\utils\fmgrprotos.h
 if %DIST%==1 if exist src\backend\utils\fmgrtab.c del /q src\backend\utils\fmgrtab.c
-- 
2.40.1

