Convert unloggedLSN to an atomic variable.
authorNathan Bossart <nathan@postgresql.org>
Thu, 29 Feb 2024 20:34:10 +0000 (14:34 -0600)
committerNathan Bossart <nathan@postgresql.org>
Thu, 29 Feb 2024 20:34:10 +0000 (14:34 -0600)
Currently, this variable is an XLogRecPtr protected by a spinlock.
By converting it to an atomic variable, we can remove the spinlock,
which saves a small amount of shared memory space.  Since this code
is not performance-critical, we use atomic operations with full
barrier semantics to make it easy to reason about correctness.

Author: John Morris
Reviewed-by: Michael Paquier, Robert Haas, Andres Freund, Stephen Frost, Bharath Rupireddy
Discussion: https://postgr.es/m/BYAPR13MB26772534335255E50318C574A0409%40BYAPR13MB2677.namprd13.prod.outlook.com
Discussion: https://postgr.es/m/MN2PR13MB2688FD8B757316CB5C54C8A2A0DDA%40MN2PR13MB2688.namprd13.prod.outlook.com

src/backend/access/transam/xlog.c

index c1162d55bff8cc97f0e62984c5c350465dcbbe44..eb02e3b6a6f82b7f2511bd26d6c921eb2d7d261f 100644 (file)
@@ -470,9 +470,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;
@@ -4498,14 +4497,7 @@ DataChecksumsEnabled(void)
 XLogRecPtr
 GetFakeLSNForUnloggedRel(void)
 {
-       XLogRecPtr      nextUnloggedLSN;
-
-       /* increment the unloggedLSN counter, need SpinLock */
-       SpinLockAcquire(&XLogCtl->ulsn_lck);
-       nextUnloggedLSN = XLogCtl->unloggedLSN++;
-       SpinLockRelease(&XLogCtl->ulsn_lck);
-
-       return nextUnloggedLSN;
+       return pg_atomic_fetch_add_u64(&XLogCtl->unloggedLSN, 1);
 }
 
 /*
@@ -4921,7 +4913,7 @@ XLOGShmemInit(void)
 
        SpinLockInit(&XLogCtl->Insert.insertpos_lck);
        SpinLockInit(&XLogCtl->info_lck);
-       SpinLockInit(&XLogCtl->ulsn_lck);
+       pg_atomic_init_u64(&XLogCtl->unloggedLSN, InvalidXLogRecPtr);
 }
 
 /*
@@ -5526,9 +5518,11 @@ StartupXLOG(void)
         * the unlogged LSN counter can be reset too.
         */
        if (ControlFile->state == DB_SHUTDOWNED)
-               XLogCtl->unloggedLSN = ControlFile->unloggedLSN;
+               pg_atomic_write_membarrier_u64(&XLogCtl->unloggedLSN,
+                                                                          ControlFile->unloggedLSN);
        else
-               XLogCtl->unloggedLSN = FirstNormalUnloggedLSN;
+               pg_atomic_write_membarrier_u64(&XLogCtl->unloggedLSN,
+                                                                          FirstNormalUnloggedLSN);
 
        /*
         * Copy any missing timeline history files between 'now' and the recovery
@@ -7110,9 +7104,7 @@ CreateCheckPoint(int flags)
         * unused on non-shutdown checkpoints, but seems useful to store it always
         * for debugging purposes.
         */
-       SpinLockAcquire(&XLogCtl->ulsn_lck);
-       ControlFile->unloggedLSN = XLogCtl->unloggedLSN;
-       SpinLockRelease(&XLogCtl->ulsn_lck);
+       ControlFile->unloggedLSN = pg_atomic_read_membarrier_u64(&XLogCtl->unloggedLSN);
 
        UpdateControlFile();
        LWLockRelease(ControlFileLock);