postgres.git / summary / log / commit / refs

commit    09a579abaca86bcd85ebc49b247d2ec58bdc6d3b
Author:   Nathan Bossart <nathan@postgresql.org>
Date:     Tue Sep 22 19:23:04 2026 +0000

    Convert SharedFileSet->refcnt to an atomic variable.
    
    Currently, this variable is an int protected by a spinlock.  By
    converting it to an atomic variable, we can remove the spinlock.
    Detaching becomes an atomic subtract, and attaching becomes a
    compare-and-exchange loop, since it must not resurrect a fileset
    whose reference count has already reached zero.
    
    Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
    Tested-by: solai v <solai.cdac@gmail.com>
    Discussion: https://postgr.es/m/alAJeRRzehDjLaF1%40nathan


src/backend/storage/file/sharedfileset.c | 33 ++++++++++++++------------------ src/include/storage/sharedfileset.h | 5 ++--- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/backend/storage/file/sharedfileset.c b/src/backend/storage/file/sharedfileset.c index d76bd72dc63..451916fc41c 100644 --- a/src/backend/storage/file/sharedfileset.c +++ b/src/backend/storage/file/sharedfileset.c @@ -38,8 +38,7 @@ void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg) { /* Initialize the shared fileset specific members. */ - SpinLockInit(&fileset->mutex); - fileset->refcnt = 1; + pg_atomic_init_u32(&fileset->refcnt, 1); /* Initialize the fileset. */ FileSetInit(&fileset->fs); @@ -55,22 +54,20 @@ SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg) void SharedFileSetAttach(SharedFileSet *fileset, dsm_segment *seg) { - bool success; + uint32 refcnt; - SpinLockAcquire(&fileset->mutex); - if (fileset->refcnt == 0) - success = false; - else + refcnt = pg_atomic_read_u32(&fileset->refcnt); + while (true) { - ++fileset->refcnt; - success = true; - } - SpinLockRelease(&fileset->mutex); + if (refcnt == 0) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("could not attach to a SharedFileSet that is already destroyed"))); - if (!success) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("could not attach to a SharedFileSet that is already destroyed"))); + if (pg_atomic_compare_exchange_u32(&fileset->refcnt, &refcnt, + refcnt + 1)) + break; + } /* Register our cleanup callback. */ on_dsm_detach(seg, SharedFileSetOnDetach, PointerGetDatum(fileset)); @@ -98,11 +95,9 @@ SharedFileSetOnDetach(dsm_segment *segment, Datum datum) bool unlink_all = false; SharedFileSet *fileset = (SharedFileSet *) DatumGetPointer(datum); - SpinLockAcquire(&fileset->mutex); - Assert(fileset->refcnt > 0); - if (--fileset->refcnt == 0) + Assert(pg_atomic_read_u32(&fileset->refcnt) > 0); + if (pg_atomic_sub_fetch_u32(&fileset->refcnt, 1) == 0) unlink_all = true; - SpinLockRelease(&fileset->mutex); /* * If we are the last to detach, we delete the directory in all diff --git a/src/include/storage/sharedfileset.h b/src/include/storage/sharedfileset.h index 904396e7173..d89626ae64b 100644 --- a/src/include/storage/sharedfileset.h +++ b/src/include/storage/sharedfileset.h @@ -15,10 +15,10 @@ #ifndef SHAREDFILESET_H #define SHAREDFILESET_H +#include "port/atomics.h" #include "storage/dsm.h" #include "storage/fd.h" #include "storage/fileset.h" -#include "storage/spin.h" /* * A set of temporary files that can be shared by multiple backends. @@ -26,8 +26,7 @@ typedef struct SharedFileSet { FileSet fs; - slock_t mutex; /* mutex protecting the reference count */ - int refcnt; /* number of attached backends */ + pg_atomic_uint32 refcnt; /* number of attached backends */ } SharedFileSet; extern void SharedFileSetInit(SharedFileSet *fileset, dsm_segment *seg);