From fa7d62f088e90b3d1c3a2e656dacd174299f538f Mon Sep 17 00:00:00 2001
From: John Morris <john.morris@crunchydata.com>
Date: Mon, 6 Nov 2023 15:53:07 -0800
Subject: [PATCH] atomic_lsn_v5

---
 src/backend/access/transam/xlog.c | 36 +++++++++++++++----------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index b541be8eec..8f033749b3 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -469,9 +469,8 @@ typedef struct XLogCtlData
 
 	XLogSegNo	lastRemovedSegNo;	/* latest removed/recycled XLOG segment */
 
-	/* Fake LSN counter, for unlogged relations. Protected by ulsn_lck. */
-	XLogRecPtr	unloggedLSN;
-	slock_t		ulsn_lck;
+	/* Fake LSN counter, for unlogged relations. */
+	pg_atomic_uint64 unloggedLSN;
 
 	/* Time and LSN of last xlog segment switch. Protected by WALWriteLock. */
 	pg_time_t	lastSegSwitchTime;
@@ -4294,13 +4293,8 @@ DataChecksumsEnabled(void)
 XLogRecPtr
 GetFakeLSNForUnloggedRel(void)
 {
-	XLogRecPtr	nextUnloggedLSN;
-
-	/* increment the unloggedLSN counter, need SpinLock */
-	SpinLockAcquire(&XLogCtl->ulsn_lck);
-	nextUnloggedLSN = XLogCtl->unloggedLSN++;
-	SpinLockRelease(&XLogCtl->ulsn_lck);
-
+	XLogRecPtr nextUnloggedLSN = pg_atomic_fetch_add_u64(&XLogCtl->unloggedLSN, 1);
+	Assert(nextUnloggedLSN != 0);
 	return nextUnloggedLSN;
 }
 
@@ -4714,7 +4708,7 @@ XLOGShmemInit(void)
 
 	SpinLockInit(&XLogCtl->Insert.insertpos_lck);
 	SpinLockInit(&XLogCtl->info_lck);
-	SpinLockInit(&XLogCtl->ulsn_lck);
+	pg_atomic_init_u64(&XLogCtl->unloggedLSN, 0);
 }
 
 /*
@@ -5319,9 +5313,9 @@ StartupXLOG(void)
 	 * the unlogged LSN counter can be reset too.
 	 */
 	if (ControlFile->state == DB_SHUTDOWNED)
-		XLogCtl->unloggedLSN = ControlFile->unloggedLSN;
+		pg_atomic_write_u64(&XLogCtl->unloggedLSN, ControlFile->unloggedLSN);
 	else
-		XLogCtl->unloggedLSN = FirstNormalUnloggedLSN;
+		pg_atomic_write_u64(&XLogCtl->unloggedLSN, FirstNormalUnloggedLSN);
 
 	/*
 	 * Copy any missing timeline history files between 'now' and the recovery
@@ -6899,13 +6893,17 @@ CreateCheckPoint(int flags)
 	ControlFile->minRecoveryPointTLI = 0;
 
 	/*
-	 * Persist unloggedLSN value. It's reset on crash recovery, so this goes
-	 * unused on non-shutdown checkpoints, but seems useful to store it always
-	 * for debugging purposes.
+	 * On shutdown, persist the unlogged LSN and reset the counter to zero.
+	 * if somebody tries to allocate another unlogged LSN, we should get an Assert() error.
+	 * On a regular checkpoint, write a zero to the control file so we
+	 * get an Assert() error if somebody accidentally uses the value in the control file.
+	 * The unlogged LSN counter should be quiescent, but we use an atomic exchange
+	 * just in case it isn't.
 	 */
-	SpinLockAcquire(&XLogCtl->ulsn_lck);
-	ControlFile->unloggedLSN = XLogCtl->unloggedLSN;
-	SpinLockRelease(&XLogCtl->ulsn_lck);
+	if (shutdown)
+		ControlFile->unloggedLSN = pg_atomic_exchange_u64(&XLogCtl->unloggedLSN, 0);
+	else
+		ControlFile->unloggedLSN = 0;
 
 	UpdateControlFile();
 	LWLockRelease(ControlFileLock);
-- 
2.33.0

