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);